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
|
||||
}
|
||||
|
||||
mut libs := ''// builtin.o os.o http.o etc
|
||||
libs := ''// builtin.o os.o http.o etc
|
||||
if v.pref.build_mode == .build_module {
|
||||
a << '-c'
|
||||
}
|
||||
else if v.pref.build_mode == .embed_vlib {
|
||||
//
|
||||
}
|
||||
else if v.pref.build_mode == .default_mode {
|
||||
/*
|
||||
// TODO
|
||||
libs = '$v_modules_path/vlib/builtin.o'
|
||||
if !os.file_exists(libs) {
|
||||
println('object file `$libs` not found')
|
||||
@ -125,6 +124,7 @@ fn (v mut V) cc() {
|
||||
}
|
||||
libs += ' "$v_modules_path/vlib/${imp}.o"'
|
||||
}
|
||||
*/
|
||||
}
|
||||
if v.pref.sanitize {
|
||||
a << '-fsanitize=leak'
|
||||
@ -248,8 +248,8 @@ fn (v mut V) cc() {
|
||||
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' {
|
||||
os.rm(v.out_name_c)
|
||||
if !v.pref.is_debug && v.out_name_c != 'v.c' {
|
||||
//os.rm(v.out_name_c)
|
||||
}
|
||||
if v.pref.compress {
|
||||
$if windows {
|
||||
|
@ -161,6 +161,9 @@ fn (g mut CGen) set_placeholder(pos int, val string) {
|
||||
}
|
||||
|
||||
fn (g mut CGen) insert_before(val string) {
|
||||
if g.nogen {
|
||||
return
|
||||
}
|
||||
prev := g.lines[g.lines.len - 1]
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -144,9 +144,8 @@ fn (p mut Parser) comp_time() {
|
||||
// #include, #flag, #v
|
||||
fn (p mut Parser) chash() {
|
||||
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()
|
||||
is_sig := p.is_sig()
|
||||
if hash.starts_with('flag ') {
|
||||
mut flag := hash.right(5)
|
||||
// expand `@VROOT` `@VMOD` to absolute path
|
||||
@ -157,7 +156,7 @@ fn (p mut Parser) chash() {
|
||||
return
|
||||
}
|
||||
if hash.starts_with('include') {
|
||||
if p.first_pass() && !is_sig {
|
||||
if p.first_pass() && !p.is_vh {
|
||||
if p.file_pcguard.len != 0 {
|
||||
//println('p: $p.file_platform $p.file_pcguard')
|
||||
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.
|
||||
fn (p mut Parser) fn_decl() {
|
||||
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))
|
||||
is_c := f.name == 'C' && p.tok == .dot
|
||||
// Just fn signature? only builtin.v + default build mode
|
||||
// is_sig := p.builtin_mod && p.pref.build_mode == default_mode
|
||||
// is_sig := p.pref.build_mode == default_mode && (p.builtin_mod || p.file.contains(LANG_TMP))
|
||||
is_sig := p.is_sig()
|
||||
// println('\n\nfn_decl() name=$f.name receiver_typ=$receiver_typ')
|
||||
if p.pref.build_mode == .build_module {
|
||||
println('\n\nfn_decl() name=$f.name receiver_typ=$receiver_typ nogen=$p.cgen.nogen')
|
||||
}
|
||||
if is_c {
|
||||
p.check(.dot)
|
||||
f.name = p.check_name()
|
||||
@ -312,13 +305,15 @@ fn (p mut Parser) fn_decl() {
|
||||
}
|
||||
p.cgen.typedefs << 'typedef struct $typ $typ;'
|
||||
}
|
||||
// Translated C code can have empty functions (just definitions)
|
||||
is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr
|
||||
// Translated C code and .vh can have empty functions (just definitions)
|
||||
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 {
|
||||
f.is_decl = true
|
||||
}
|
||||
// { 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.check(.lcbr)
|
||||
}
|
||||
@ -350,7 +345,7 @@ fn (p mut Parser) fn_decl() {
|
||||
mut fn_name_cgen := p.table.fn_gen_name(f)
|
||||
// Start generation of the function body
|
||||
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 {
|
||||
p.genln('; // $f.name')
|
||||
}
|
||||
@ -403,10 +398,10 @@ fn (p mut Parser) fn_decl() {
|
||||
// println('register_fn typ=$typ isg=$is_generic')
|
||||
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
|
||||
// Look for generic calls.
|
||||
if !is_sig && !is_fn_header {
|
||||
if !p.is_vh && !is_fn_header {
|
||||
p.skip_fn_body()
|
||||
}
|
||||
// Live code reloading? Load all fns from .so
|
||||
@ -422,19 +417,8 @@ fn (p mut Parser) fn_decl() {
|
||||
}
|
||||
// Add function definition to the top
|
||||
if !is_c && p.first_pass() {
|
||||
// TODO hack to make Volt compile without -embed_vlib
|
||||
if f.name == 'darwin__nsstring' && p.pref.build_mode == .default_mode {
|
||||
|
||||
} else {
|
||||
p.cgen.fns << fn_decl + ';'
|
||||
}
|
||||
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
|
||||
}
|
||||
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')
|
||||
if is_c || is_sig || is_fn_header {
|
||||
// println('IS SIG .key_returnING tok=${p.strtok()}')
|
||||
if is_c || p.is_vh || is_fn_header {
|
||||
return
|
||||
}
|
||||
// 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.statements_no_rcbr()
|
||||
p.cgen.nogen = false
|
||||
//p.cgen.nogen = false
|
||||
// Print counting result after all statements in main
|
||||
if p.pref.is_prof && f.name == 'main' {
|
||||
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 {
|
||||
p.gen('$tmp')
|
||||
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 {
|
||||
if p.pref.translated && !p.builtin_mod {
|
||||
@ -214,18 +215,18 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
|
||||
// Obfuscate but skip certain names
|
||||
// TODO ugly, fix
|
||||
// NB: the order here is from faster to potentially slower checks
|
||||
if table.obfuscate &&
|
||||
if table.obfuscate &&
|
||||
!f.is_c &&
|
||||
f.name != 'main' && f.name != 'WinMain' && f.name != 'main__main' &&
|
||||
f.name != 'main' && f.name != 'WinMain' && f.name != 'main__main' &&
|
||||
f.name != 'gg__vec2' &&
|
||||
f.name != 'build_token_str' &&
|
||||
f.name != 'build_keys' &&
|
||||
f.mod != 'builtin' &&
|
||||
f.mod != 'darwin' &&
|
||||
f.mod != 'os' &&
|
||||
f.name != 'build_token_str' &&
|
||||
f.name != 'build_keys' &&
|
||||
f.mod != 'builtin' &&
|
||||
f.mod != 'darwin' &&
|
||||
f.mod != 'os' &&
|
||||
f.mod != 'json' &&
|
||||
!f.name.contains('window_proc') &&
|
||||
!name.ends_with('_str') &&
|
||||
!f.name.contains('window_proc') &&
|
||||
!name.ends_with('_str') &&
|
||||
!name.contains('contains') {
|
||||
mut idx := table.obf_ids[name]
|
||||
// No such function yet, register it
|
||||
|
104
compiler/main.v
104
compiler/main.v
@ -18,9 +18,6 @@ enum BuildMode {
|
||||
// `v program.v'
|
||||
// Build user code only, and add pre-compiled vlib (`cc program.o builtin.o os.o...`)
|
||||
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`
|
||||
// build any module (generate os.o + os.vh)
|
||||
build_module
|
||||
@ -290,36 +287,25 @@ fn (v mut V) compile() {
|
||||
cgen.genln('#define V_COMMIT_HASH "' + vhash() + '"')
|
||||
cgen.genln('#endif')
|
||||
}
|
||||
|
||||
q := cgen.nogen // TODO hack
|
||||
cgen.nogen = false
|
||||
$if js {
|
||||
cgen.genln(js_headers)
|
||||
} $else {
|
||||
cgen.genln(CommonCHeaders)
|
||||
}
|
||||
|
||||
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
|
||||
// default mode
|
||||
imports_json := 'json' in v.table.imports
|
||||
if v.pref.build_mode == .default_mode {
|
||||
if imports_json {
|
||||
cgen.genln('#include "cJSON.h"')
|
||||
}
|
||||
}
|
||||
if v.pref.build_mode == .embed_vlib || v.pref.build_mode == .default_mode {
|
||||
//if v.pref.build_mode in [.embed_vlib, .default_mode] {
|
||||
if v.pref.build_mode == .default_mode {
|
||||
// If we declare these for all modes, then when running `v a.v` we'll get
|
||||
// `/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 {
|
||||
cgen.genln('int g_test_oks = 0;')
|
||||
cgen.genln('int g_test_fails = 0;')
|
||||
@ -335,11 +321,14 @@ fn (v mut V) compile() {
|
||||
}
|
||||
//cgen.genln('/*================================== FNS =================================*/')
|
||||
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 {
|
||||
v.parse(file, .main)
|
||||
//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)
|
||||
if !v.pref.nofmt && !file.contains('/vlib/') {
|
||||
// new vfmt is not ready yet
|
||||
@ -356,25 +345,25 @@ fn (v mut V) compile() {
|
||||
vgen_parser.parse(.main)
|
||||
// v.parsers.add(vgen_parser)
|
||||
v.log('Done parsing.')
|
||||
// Write everything
|
||||
mut d := strings.new_builder(10000)// Avoid unnecessary allocations
|
||||
// All definitions
|
||||
mut def := strings.new_builder(10000)// Avoid unnecessary allocations
|
||||
$if !js {
|
||||
d.writeln(cgen.includes.join_lines())
|
||||
d.writeln(cgen.typedefs.join_lines())
|
||||
d.writeln(v.type_definitions())
|
||||
d.writeln('\nstring _STR(const char*, ...);\n')
|
||||
d.writeln('\nstring _STR_TMP(const char*, ...);\n')
|
||||
d.writeln(cgen.fns.join_lines()) // fn definitions
|
||||
def.writeln(cgen.includes.join_lines())
|
||||
def.writeln(cgen.typedefs.join_lines())
|
||||
def.writeln(v.type_definitions())
|
||||
def.writeln('\nstring _STR(const char*, ...);\n')
|
||||
def.writeln('\nstring _STR_TMP(const char*, ...);\n')
|
||||
def.writeln(cgen.fns.join_lines()) // fn definitions
|
||||
} $else {
|
||||
d.writeln(v.type_definitions())
|
||||
def.writeln(v.type_definitions())
|
||||
}
|
||||
d.writeln(cgen.consts.join_lines())
|
||||
d.writeln(cgen.thread_args.join_lines())
|
||||
def.writeln(cgen.consts.join_lines())
|
||||
def.writeln(cgen.thread_args.join_lines())
|
||||
if v.pref.is_prof {
|
||||
d.writeln('; // Prof counters:')
|
||||
d.writeln(v.prof_counters())
|
||||
def.writeln('; // Prof counters:')
|
||||
def.writeln(v.prof_counters())
|
||||
}
|
||||
cgen.lines[defs_pos] = d.str()
|
||||
cgen.lines[defs_pos] = def.str()
|
||||
v.generate_main()
|
||||
v.generate_hot_reload_code()
|
||||
if v.pref.is_verbose {
|
||||
@ -394,8 +383,7 @@ fn (v mut V) generate_main() {
|
||||
mut cgen := v.cgen
|
||||
$if js { return }
|
||||
|
||||
// if v.build_mode in [.default, .embed_vlib] {
|
||||
if v.pref.build_mode == .default_mode || v.pref.build_mode == .embed_vlib {
|
||||
if v.pref.build_mode == .default_mode {
|
||||
mut consts_init_body := cgen.consts_init.join_lines()
|
||||
// vlib can't have `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
|
||||
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
|
||||
for file in v.get_builtin_files() {
|
||||
for file in builtin_files {
|
||||
// add builtins first
|
||||
v.files << 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:')
|
||||
println(v.table.imports)
|
||||
}
|
||||
// resolve deps & add imports in correct order
|
||||
for mod in v.resolve_deps().imports() {
|
||||
// if mod == v.mod { continue } // Building this module? Skip. TODO it's a hack.
|
||||
if mod == 'builtin' { continue } // builtin already added
|
||||
if mod == 'main' { continue } // main files will get added last
|
||||
// resolve deps and add imports in correct order
|
||||
imported_mods := v.resolve_deps().imports()
|
||||
for mod in imported_mods {
|
||||
if mod == 'builtin' || mod == 'main' {
|
||||
// builtin already added
|
||||
// main files will get added last
|
||||
continue
|
||||
}
|
||||
|
||||
// use cached built module if exists
|
||||
// vh_path := '$v_modules_path/${mod}.vh'
|
||||
// if os.file_exists(vh_path) {
|
||||
// println('using cached module `$mod`: $vh_path')
|
||||
// v.files << vh_path
|
||||
// continue
|
||||
// }
|
||||
if v.pref.build_mode != .build_module {
|
||||
vh_path := '$v_modules_path/${mod}.vh'
|
||||
//println(vh_path)
|
||||
if v.pref.is_debug && os.file_exists(vh_path) {
|
||||
println('using cached module `$mod`: $vh_path')
|
||||
v.files << vh_path
|
||||
continue
|
||||
}
|
||||
}
|
||||
// standard module
|
||||
mod_path := v.find_module_path(mod) or { verror(err) break }
|
||||
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 {
|
||||
// .vh cache exists? Use it
|
||||
|
||||
$if 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_script := dir.ends_with('.v')
|
||||
if is_script && !os.file_exists(dir) {
|
||||
|
@ -9,9 +9,10 @@ import (
|
||||
os
|
||||
)
|
||||
|
||||
/* .vh generation logic.
|
||||
.vh files contains only function signatures, consts, and types.
|
||||
They are used together with pre-compiled modules.
|
||||
/*
|
||||
.vh generation logic.
|
||||
.vh files contains only function signatures, consts, and types.
|
||||
They are used together with pre-compiled modules.
|
||||
*/
|
||||
|
||||
// "fn foo(a int) string"
|
||||
@ -27,7 +28,7 @@ fn (f &Fn) v_definition() string {
|
||||
}
|
||||
if f.is_method {
|
||||
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 { '' }
|
||||
if recv.ref {
|
||||
mu = '&'
|
||||
@ -40,6 +41,9 @@ fn (f &Fn) v_definition() string {
|
||||
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)
|
||||
if arg.name == '' {
|
||||
sb.write(typ)
|
||||
@ -62,11 +66,12 @@ fn (f &Fn) v_definition() string {
|
||||
}
|
||||
|
||||
fn v_type_str(typ_ string) string {
|
||||
typ := if typ_.ends_with('*') {
|
||||
mut typ := if typ_.ends_with('*') {
|
||||
'*' + typ_.left(typ_.len - 1)
|
||||
} else {
|
||||
typ_
|
||||
}
|
||||
typ = typ.replace('Option_', '?')
|
||||
//println('"$typ"')
|
||||
if typ == '*void' {
|
||||
return 'voidptr'
|
||||
@ -80,11 +85,11 @@ fn v_type_str(typ_ string) string {
|
||||
if typ.contains('__') {
|
||||
return typ.all_after('__')
|
||||
}
|
||||
return typ.replace('Option_', '?')
|
||||
return typ
|
||||
}
|
||||
|
||||
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'
|
||||
path := dir + '.vh'
|
||||
if !os.dir_exists(dir) {
|
||||
@ -95,6 +100,7 @@ fn (v &V) generate_vh() {
|
||||
file := os.create(path) or { panic(err) }
|
||||
// Consts
|
||||
file.writeln('// $v.mod module header \n')
|
||||
file.writeln('module $v.mod')
|
||||
file.writeln('// Consts')
|
||||
if v.table.consts.len > 0 {
|
||||
file.writeln('const (')
|
||||
@ -126,16 +132,20 @@ fn (v &V) generate_vh() {
|
||||
file.writeln('\n')
|
||||
}
|
||||
// Types
|
||||
file.writeln('// Types')
|
||||
file.writeln('// Types2')
|
||||
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
|
||||
}
|
||||
mut name := typ.name
|
||||
if typ.name.contains('__') {
|
||||
continue
|
||||
name = typ.name.all_after('__')
|
||||
}
|
||||
if typ.cat == .struct_ {
|
||||
file.writeln('struct $typ.name {')
|
||||
if typ.cat in [TypeCategory.struct_, .c_struct] {
|
||||
c := if typ.is_c { 'C.' } else { '' }
|
||||
file.writeln('struct ${c}$name {')
|
||||
// Private fields
|
||||
for field in typ.fields {
|
||||
if field.access_mod == .public {
|
||||
@ -144,13 +154,18 @@ fn (v &V) generate_vh() {
|
||||
field_type := v_type_str(field.typ)
|
||||
file.writeln('\t$field.name $field_type')
|
||||
}
|
||||
file.writeln('pub:')
|
||||
//file.writeln('pub:')
|
||||
mut public_str := ''
|
||||
for field in typ.fields {
|
||||
if field.access_mod == .private {
|
||||
continue
|
||||
}
|
||||
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')
|
||||
}
|
||||
@ -161,8 +176,10 @@ fn (v &V) generate_vh() {
|
||||
mut fns := []Fn
|
||||
// TODO fns := v.table.fns.filter(.mod == v.mod)
|
||||
for _, f in v.table.fns {
|
||||
if f.mod == v.mod {
|
||||
if f.mod == v.mod || f.mod == ''{
|
||||
fns << f
|
||||
} else {
|
||||
println('skipping fn $f.name mod=$f.mod')
|
||||
}
|
||||
}
|
||||
for _, f in fns {
|
||||
@ -181,7 +198,8 @@ fn (v &V) generate_vh() {
|
||||
// Methods
|
||||
file.writeln('\n// Methods //////////////////')
|
||||
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
|
||||
}
|
||||
for method in typ.methods {
|
||||
|
@ -29,7 +29,7 @@ const (
|
||||
KEY_ENUMERATE_SUB_KEYS = (0x0008)
|
||||
)
|
||||
|
||||
// Given a root key look for one of the subkeys in 'versions' and get the path
|
||||
// Given a root key look for one of the subkeys in 'versions' and get the path
|
||||
fn find_windows_kit_internal(key RegKey, versions []string) ?string {
|
||||
$if windows {
|
||||
for version in versions {
|
||||
@ -139,7 +139,7 @@ fn find_vs() ?VsInstallation {
|
||||
}
|
||||
// Emily:
|
||||
// VSWhere is guaranteed to be installed at this location now
|
||||
// If its not there then end user needs to update their visual studio
|
||||
// If its not there then end user needs to update their visual studio
|
||||
// installation!
|
||||
res := os.exec('""%ProgramFiles(x86)%\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath"') or {
|
||||
return error(err)
|
||||
@ -207,7 +207,7 @@ fn find_msvc() ?MsvcResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (v mut V) cc_msvc() {
|
||||
pub fn (v mut V) cc_msvc() {
|
||||
r := find_msvc() or {
|
||||
// TODO: code reuse
|
||||
if !v.pref.is_debug && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' {
|
||||
@ -253,9 +253,6 @@ pub fn (v mut V) cc_msvc() {
|
||||
mut alibs := []string // builtin.o os.o http.o etc
|
||||
if v.pref.build_mode == .build_module {
|
||||
}
|
||||
else if v.pref.build_mode == .embed_vlib {
|
||||
//
|
||||
}
|
||||
else if v.pref.build_mode == .default_mode {
|
||||
b := os.realpath( '$v_modules_path/vlib/builtin.obj' )
|
||||
alibs << '"$b"'
|
||||
@ -334,8 +331,8 @@ pub fn (v mut V) cc_msvc() {
|
||||
|
||||
args := a.join(' ')
|
||||
|
||||
cmd := '""$r.full_cl_exe_path" $args"'
|
||||
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
||||
cmd := '""$r.full_cl_exe_path" $args"'
|
||||
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
||||
// Also the double quotes at the start ARE needed.
|
||||
if v.pref.show_c_cmd || v.pref.is_verbose {
|
||||
println('\n========== cl cmd line:')
|
||||
@ -376,16 +373,16 @@ fn build_thirdparty_obj_file_with_msvc(path string, moduleflags []CFlag) {
|
||||
|
||||
if os.file_exists(obj_path) {
|
||||
println('$obj_path already build.')
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
println('$obj_path not found, building it (with msvc)...')
|
||||
println('$obj_path not found, building it (with msvc)...')
|
||||
parent := os.dir(obj_path)
|
||||
files := os.ls(parent)
|
||||
|
||||
mut cfiles := ''
|
||||
mut cfiles := ''
|
||||
for file in files {
|
||||
if file.ends_with('.c') {
|
||||
if file.ends_with('.c') {
|
||||
cfiles += '"' + os.realpath( parent + os.PathSeparator + file ) + '" '
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ mut:
|
||||
tmp_cnt int
|
||||
is_script bool
|
||||
builtin_mod bool
|
||||
vh_lines []string
|
||||
inside_if_expr bool
|
||||
inside_unwrapping_match_statement bool
|
||||
inside_return_expr bool
|
||||
@ -73,7 +72,7 @@ mut:
|
||||
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
|
||||
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
|
||||
is_vweb bool
|
||||
is_sql bool
|
||||
@ -81,6 +80,7 @@ mut:
|
||||
sql_i int // $1 $2 $3
|
||||
sql_params []string // ("select * from users where id = $1", ***"100"***)
|
||||
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 (
|
||||
@ -100,7 +100,6 @@ fn (v mut V) new_parser_from_string(text string, id string) Parser {
|
||||
return p
|
||||
}
|
||||
|
||||
// new parser from file.
|
||||
fn (v mut V) new_parser_from_file(path string) Parser {
|
||||
//println('new_parser("$path")')
|
||||
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_platform: path_platform,
|
||||
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 {
|
||||
p.scanner.should_print_relative_paths_on_error = false
|
||||
@ -249,6 +249,14 @@ fn (p mut Parser) parse(pass Pass) {
|
||||
p.fspace()
|
||||
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.builtin_mod = p.mod == 'builtin'
|
||||
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)
|
||||
if p.tok == .assign {
|
||||
p.next()
|
||||
// p.gen(' = ')
|
||||
g += ' = '
|
||||
p.cgen.start_tmp()
|
||||
p.bool_expression()
|
||||
// g += '<<< ' + p.cgen.end_tmp() + '>>>'
|
||||
g += p.cgen.end_tmp()
|
||||
_, expr := p.tmp_expr()
|
||||
g += expr
|
||||
}
|
||||
// p.genln('; // global')
|
||||
g += '; // global'
|
||||
p.cgen.consts << g
|
||||
if !p.cgen.nogen {
|
||||
p.cgen.consts << g
|
||||
}
|
||||
case TokenKind.eof:
|
||||
//p.log('end of parse()')
|
||||
// TODO: check why this was added? everything seems to work
|
||||
@ -484,27 +491,36 @@ fn (p mut Parser) const_decl() {
|
||||
p.fgenln('')
|
||||
p.fmt_inc()
|
||||
for p.tok == .name {
|
||||
if p.lit == '_' && p.peek() == .assign {
|
||||
if p.lit == '_' && p.peek() == .assign && !p.cgen.nogen {
|
||||
p.gen_blank_identifier_assign()
|
||||
//if !p.cgen.nogen {
|
||||
p.cgen.consts_init << p.cgen.cur_line.trim_space()
|
||||
p.cgen.resetln('')
|
||||
//}
|
||||
continue
|
||||
}
|
||||
// `Age = 20`
|
||||
mut name := p.check_name()
|
||||
mut name := p.check_name() // `Age = 20`
|
||||
//if ! (name[0] >= `A` && name[0] <= `Z`) {
|
||||
//p.error('const name must be capitalized')
|
||||
//}
|
||||
name = p.prepend_mod(name)
|
||||
p.check_space(.assign)
|
||||
typ := p.expression()
|
||||
mut typ := ''
|
||||
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) {
|
||||
p.error('redefinition of `$name`')
|
||||
}
|
||||
if p.first_pass() {
|
||||
p.table.register_const(name, typ, p.mod)
|
||||
}
|
||||
if p.pass == .main {
|
||||
if p.pass == .main && !p.cgen.nogen {
|
||||
// TODO hack
|
||||
// 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
|
||||
@ -1219,11 +1235,6 @@ fn (p mut Parser) gen(s string) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if p.returns && !p.is_vweb {
|
||||
p.error('unreachable code')
|
||||
@ -2806,7 +2817,7 @@ fn (p mut Parser) string_expr() {
|
||||
p.gen('"$f"')
|
||||
}
|
||||
else {
|
||||
p.gen('tos2((byte*)"$f")')
|
||||
p.gen('tos3("$f")')
|
||||
}
|
||||
p.next()
|
||||
return
|
||||
|
@ -70,8 +70,4 @@ Options/commands:
|
||||
/*
|
||||
- To disable automatic formatting:
|
||||
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
|
||||
for i := 0; i < a.len-1; i++ {
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
struct C.time_t {}
|
||||
|
||||
struct C.tm {
|
||||
tm_year int
|
||||
tm_mon int
|
||||
|
Loading…
Reference in New Issue
Block a user