fmt: lots of fixes
parent
7c080c5d4a
commit
fb54a2635c
|
@ -8,9 +8,9 @@ import v.table
|
|||
|
||||
pub type TypeDecl = AliasTypeDecl | SumTypeDecl | FnTypeDecl
|
||||
|
||||
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr | IndexExpr | RangeExpr | MatchExpr | CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr | ConcatExpr | Type | AsCast | TypeOf | StringInterLiteral | AnonFn
|
||||
pub type Expr = AnonFn | ArrayInit | AsCast | AssignExpr | Assoc | BoolLiteral | CastExpr | CallExpr | CharLiteral | ConcatExpr | EnumVal | FloatLiteral | IfExpr | Ident | IfGuardExpr | InfixExpr | IndexExpr | IntegerLiteral | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | StringLiteral | StringInterLiteral | StructInit | Type | TypeOf
|
||||
|
||||
pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | Comment | AssertStmt | UnsafeStmt | GoStmt | Block | InterfaceDecl
|
||||
pub type Stmt = AssignStmt | AssertStmt | Attr | Block | BranchStmt | Comment | CompIf | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | StructDecl | TypeDecl | UnsafeStmt
|
||||
|
||||
pub type ScopeObject = ConstField | GlobalDecl | Var
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ pub fn (node &FnDecl) str(t &table.Table) string {
|
|||
receiver = '($node.receiver.name $m$name) '
|
||||
*/
|
||||
}
|
||||
mut name := node.name.after('.')
|
||||
mut name := if node.is_anon { '' } else { node.name.after('.') }
|
||||
if node.is_c {
|
||||
name = 'C.$name'
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ pub fn new_builder(pref &pref.Preferences) Builder {
|
|||
}
|
||||
|
||||
// parse all deps from already parsed files
|
||||
pub fn (b mut Builder) parse_imports() {
|
||||
pub fn (mut b Builder) parse_imports() {
|
||||
mut done_imports := []string
|
||||
// NB: b.parsed_files is appended in the loop,
|
||||
// so we can not use the shorter `for in` form.
|
||||
|
@ -84,7 +84,7 @@ pub fn (b mut Builder) parse_imports() {
|
|||
b.resolve_deps()
|
||||
}
|
||||
|
||||
pub fn (b mut Builder) resolve_deps() {
|
||||
pub fn (mut b Builder) resolve_deps() {
|
||||
graph := b.import_graph()
|
||||
deps_resolved := graph.resolve()
|
||||
if !deps_resolved.acyclic {
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
module builder
|
||||
|
||||
import (
|
||||
time
|
||||
os
|
||||
v.parser
|
||||
v.pref
|
||||
v.gen
|
||||
)
|
||||
import time
|
||||
import os
|
||||
import v.parser
|
||||
import v.pref
|
||||
import v.gen
|
||||
|
||||
pub fn (b mut Builder) gen_c(v_files []string) string {
|
||||
pub fn (mut b Builder) gen_c(v_files []string) string {
|
||||
t0 := time.ticks()
|
||||
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
||||
b.parse_imports()
|
||||
|
@ -35,7 +33,7 @@ pub fn (b mut Builder) gen_c(v_files []string) string {
|
|||
return res
|
||||
}
|
||||
|
||||
pub fn (b mut Builder) build_c(v_files []string, out_file string) {
|
||||
pub fn (mut b Builder) build_c(v_files []string, out_file string) {
|
||||
b.out_name_c = out_file
|
||||
b.info('build_c($out_file)')
|
||||
mut f := os.create(out_file) or {
|
||||
|
@ -46,7 +44,7 @@ pub fn (b mut Builder) build_c(v_files []string, out_file string) {
|
|||
// os.write_file(out_file, b.gen_c(v_files))
|
||||
}
|
||||
|
||||
pub fn (b mut Builder) compile_c() {
|
||||
pub fn (mut b Builder) compile_c() {
|
||||
if os.user_os() != 'windows' && b.pref.ccompiler == 'msvc' {
|
||||
verror('Cannot build with msvc on ${os.user_os()}')
|
||||
}
|
||||
|
@ -54,7 +52,7 @@ pub fn (b mut Builder) compile_c() {
|
|||
// println('compile2()')
|
||||
if b.pref.is_verbose {
|
||||
println('all .v files before:')
|
||||
//println(files)
|
||||
// println(files)
|
||||
}
|
||||
// v1 compiler files
|
||||
// v.add_v_files_to_compile()
|
||||
|
|
|
@ -3,21 +3,19 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module builder
|
||||
|
||||
import (
|
||||
os
|
||||
time
|
||||
v.cflag
|
||||
v.pref
|
||||
v.util
|
||||
term
|
||||
)
|
||||
import os
|
||||
import time
|
||||
import v.cflag
|
||||
import v.pref
|
||||
import v.util
|
||||
import term
|
||||
|
||||
fn todo() {
|
||||
}
|
||||
|
||||
fn (v &Builder) no_cc_installed() bool {
|
||||
$if windows {
|
||||
os.exec('$v.pref.ccompiler -v')or{
|
||||
os.exec('$v.pref.ccompiler -v') or {
|
||||
if v.pref.is_verbose {
|
||||
println('C compiler not found, trying to build with msvc...')
|
||||
}
|
||||
|
@ -27,7 +25,7 @@ fn (v &Builder) no_cc_installed() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
fn (v mut Builder) cc() {
|
||||
fn (mut v Builder) cc() {
|
||||
if os.executable().contains('vfmt') {
|
||||
return
|
||||
}
|
||||
|
@ -55,8 +53,7 @@ fn (v mut Builder) cc() {
|
|||
ret := os.system('$vexe -o $vjs_path -os js $vdir/cmd/v')
|
||||
if ret == 0 {
|
||||
println('Done.')
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
println('Failed.')
|
||||
exit(1)
|
||||
}
|
||||
|
@ -69,7 +66,7 @@ fn (v mut Builder) cc() {
|
|||
}
|
||||
}
|
||||
// v.out_name_c may be on a different partition than v.out_name
|
||||
os.mv_by_cp(v.out_name_c, v.pref.out_name)or{
|
||||
os.mv_by_cp(v.out_name_c, v.pref.out_name) or {
|
||||
panic(err)
|
||||
}
|
||||
exit(0)
|
||||
|
@ -88,14 +85,16 @@ fn (v mut Builder) cc() {
|
|||
}
|
||||
}
|
||||
// arguments for the C compiler
|
||||
mut a := [v.pref.cflags, '-std=gnu11', '-Wall', '-Wextra',
|
||||
mut a := [ v.pref.cflags, '-std=gnu11', '-Wall', '-Wextra',
|
||||
// TODO : activate -Werror once no warnings remain
|
||||
// '-Werror',
|
||||
// TODO : try and remove the below workaround options when the corresponding
|
||||
// warnings are totally fixed/removed
|
||||
'-Wno-unused-variable',
|
||||
// '-Wno-unused-but-set-variable',
|
||||
'-Wno-unused-parameter', '-Wno-unused-result', '-Wno-unused-function', '-Wno-missing-braces', '-Wno-unused-label']
|
||||
'-Wno-unused-parameter', '-Wno-unused-result', '-Wno-unused-function', '-Wno-missing-braces',
|
||||
'-Wno-unused-label'
|
||||
]
|
||||
// TCC on Linux by default, unless -cc was provided
|
||||
// TODO if -cc = cc, TCC is still used, default compiler should be
|
||||
// used instead.
|
||||
|
@ -125,15 +124,10 @@ fn (v mut Builder) cc() {
|
|||
verror('-fast is only supported on Linux right now')
|
||||
}
|
||||
}
|
||||
|
||||
if !v.pref.is_shared
|
||||
&& v.pref.build_mode != .build_module
|
||||
&& os.user_os() == 'windows'
|
||||
&& !v.pref.out_name.ends_with('.exe')
|
||||
{
|
||||
if !v.pref.is_shared && v.pref.build_mode != .build_module && os.user_os() == 'windows' &&
|
||||
!v.pref.out_name.ends_with('.exe') {
|
||||
v.pref.out_name += '.exe'
|
||||
}
|
||||
|
||||
// linux_host := os.user_os() == 'linux'
|
||||
v.log('cc() isprod=$v.pref.is_prod outname=$v.pref.out_name')
|
||||
if v.pref.is_shared {
|
||||
|
@ -159,7 +153,7 @@ fn (v mut Builder) cc() {
|
|||
mut guessed_compiler := v.pref.ccompiler
|
||||
if guessed_compiler == 'cc' && v.pref.is_prod {
|
||||
// deliberately guessing only for -prod builds for performance reasons
|
||||
if ccversion:=os.exec('cc --version'){
|
||||
if ccversion := os.exec('cc --version') {
|
||||
if ccversion.exit_code == 0 {
|
||||
if ccversion.output.contains('This is free software;') && ccversion.output.contains('Free Software Foundation, Inc.') {
|
||||
guessed_compiler = 'gcc'
|
||||
|
@ -221,8 +215,7 @@ fn (v mut Builder) cc() {
|
|||
mut libs := '' // builtin.o os.o http.o etc
|
||||
if v.pref.build_mode == .build_module {
|
||||
a << '-c'
|
||||
}
|
||||
else if v.pref.is_cache {
|
||||
} else if v.pref.is_cache {
|
||||
/*
|
||||
QTODO
|
||||
builtin_o_path := os.join_path(pref.default_module_path, 'cache', 'vlib', 'builtin.o')
|
||||
|
@ -268,7 +261,6 @@ fn (v mut Builder) cc() {
|
|||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if v.pref.sanitize {
|
||||
a << '-fsanitize=leak'
|
||||
}
|
||||
|
@ -289,7 +281,7 @@ fn (v mut Builder) cc() {
|
|||
// Output executable name
|
||||
a << '-o "$v.pref.out_name"'
|
||||
if os.is_dir(v.pref.out_name) {
|
||||
verror("\'$v.pref.out_name\' is a directory")
|
||||
verror("'$v.pref.out_name' is a directory")
|
||||
}
|
||||
// macOS code can include objective C TODO remove once objective C is replaced with C
|
||||
if v.pref.os == .mac {
|
||||
|
@ -313,9 +305,8 @@ fn (v mut Builder) cc() {
|
|||
// add all flags (-I -l -L etc) not .o files
|
||||
a << cflags.c_options_without_object_files()
|
||||
a << libs
|
||||
|
||||
if v.pref.is_cache {
|
||||
cached_files := ['builtin.o', 'math.o']
|
||||
cached_files := [ 'builtin.o', 'math.o']
|
||||
for cfile in cached_files {
|
||||
ofile := os.join_path(pref.default_module_path, 'cache', 'vlib', cfile)
|
||||
if os.exists(ofile) {
|
||||
|
@ -328,10 +319,10 @@ fn (v mut Builder) cc() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Without these libs compilation will fail on Linux
|
||||
// || os.user_os() == 'linux'
|
||||
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in [.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
|
||||
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in [ .linux, .freebsd,
|
||||
.openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
|
||||
a << '-lm -lpthread '
|
||||
// -ldl is a Linux only thing. BSDs have it in libc.
|
||||
if v.pref.os == .linux {
|
||||
|
@ -346,7 +337,7 @@ fn (v mut Builder) cc() {
|
|||
a << '-lm'
|
||||
}
|
||||
args := a.join(' ')
|
||||
start:
|
||||
start:
|
||||
todo()
|
||||
// TODO remove
|
||||
cmd := '${v.pref.ccompiler} $args'
|
||||
|
@ -356,7 +347,7 @@ start:
|
|||
println(cmd)
|
||||
}
|
||||
ticks := time.ticks()
|
||||
res := os.exec(cmd)or{
|
||||
res := os.exec(cmd) or {
|
||||
// C compilation failed.
|
||||
// If we are on Windows, try msvc
|
||||
println('C compilation failed.')
|
||||
|
@ -367,7 +358,6 @@ start:
|
|||
return
|
||||
}
|
||||
*/
|
||||
|
||||
verror(err)
|
||||
return
|
||||
}
|
||||
|
@ -381,7 +371,9 @@ start:
|
|||
goto start
|
||||
}
|
||||
}
|
||||
verror('C compiler error, while attempting to run: \n' + '-----------------------------------------------------------\n' + '$cmd\n' + '-----------------------------------------------------------\n' + 'Probably your C compiler is missing. \n' + 'Please reinstall it, or make it available in your PATH.\n\n' + missing_compiler_info())
|
||||
verror('C compiler error, while attempting to run: \n' + '-----------------------------------------------------------\n' +
|
||||
'$cmd\n' + '-----------------------------------------------------------\n' + 'Probably your C compiler is missing. \n' +
|
||||
'Please reinstall it, or make it available in your PATH.\n\n' + missing_compiler_info())
|
||||
}
|
||||
if v.pref.is_debug {
|
||||
eword := 'error:'
|
||||
|
@ -399,12 +391,11 @@ If you were not working with C interop and are not sure about what's happening,
|
|||
please put the whole output in a pastebin and contact us through the following ways with a link to the pastebin:
|
||||
- Raise an issue on GitHub: https://github.com/vlang/v/issues/new/choose
|
||||
- Ask a question in #help on Discord: https://discord.gg/vlang")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if res.output.len < 30 {
|
||||
println(res.output)
|
||||
} else {
|
||||
elines := error_context_lines( res.output, 'error:', 1, 12 )
|
||||
elines := error_context_lines(res.output, 'error:', 1, 12)
|
||||
println('==================')
|
||||
for eline in elines {
|
||||
println(eline)
|
||||
|
@ -451,7 +442,6 @@ If you're confident that all of the above is true, please try running V with the
|
|||
println('linux cross compilation done. resulting binary: "$v.out_name"')
|
||||
}
|
||||
*/
|
||||
|
||||
if !v.pref.is_keep_c && v.out_name_c != 'v.c' {
|
||||
os.rm(v.out_name_c)
|
||||
}
|
||||
|
@ -486,7 +476,7 @@ If you're confident that all of the above is true, please try running V with the
|
|||
}
|
||||
}
|
||||
|
||||
fn (c mut Builder) cc_windows_cross() {
|
||||
fn (mut c Builder) cc_windows_cross() {
|
||||
/*
|
||||
QTODO
|
||||
println('Cross compiling for Windows...')
|
||||
|
@ -568,8 +558,7 @@ fn (c &Builder) build_thirdparty_obj_files() {
|
|||
rest_of_module_flags := c.get_rest_of_module_cflags(flag)
|
||||
if c.pref.ccompiler == 'msvc' || c.no_cc_installed() {
|
||||
build_thirdparty_obj_file_with_msvc(flag.value, rest_of_module_flags)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
c.build_thirdparty_obj_file(flag.value, rest_of_module_flags)
|
||||
}
|
||||
}
|
||||
|
@ -583,7 +572,7 @@ fn (v &Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CFlag
|
|||
}
|
||||
println('$obj_path not found, building it...')
|
||||
parent := os.dir(obj_path)
|
||||
files := os.ls(parent)or{
|
||||
files := os.ls(parent) or {
|
||||
panic(err)
|
||||
}
|
||||
mut cfiles := ''
|
||||
|
@ -595,7 +584,7 @@ fn (v &Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CFlag
|
|||
btarget := moduleflags.c_options_before_target()
|
||||
atarget := moduleflags.c_options_after_target()
|
||||
cmd := '$v.pref.ccompiler $v.pref.third_party_option $btarget -c -o "$obj_path" $cfiles $atarget '
|
||||
res := os.exec(cmd)or{
|
||||
res := os.exec(cmd) or {
|
||||
println('failed thirdparty object build cmd: $cmd')
|
||||
verror(err)
|
||||
return
|
||||
|
|
|
@ -36,4 +36,3 @@ fn (v &Builder) get_rest_of_module_cflags(c &cflag.CFlag) []cflag.CFlag {
|
|||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module builder
|
||||
|
||||
import (
|
||||
benchmark
|
||||
os
|
||||
v.pref
|
||||
v.util
|
||||
strings
|
||||
)
|
||||
import benchmark
|
||||
import os
|
||||
import v.pref
|
||||
import v.util
|
||||
import strings
|
||||
|
||||
fn get_vtmp_folder() string {
|
||||
vtmp := os.join_path(os.temp_dir(), 'v')
|
||||
|
@ -35,9 +33,15 @@ pub fn compile(command string, pref &pref.Preferences) {
|
|||
}
|
||||
mut tmark := benchmark.new_benchmark()
|
||||
match pref.backend {
|
||||
.c { b.compile_c() }
|
||||
.js { b.compile_js() }
|
||||
.x64 { b.compile_x64() }
|
||||
.c {
|
||||
b.compile_c()
|
||||
}
|
||||
.js {
|
||||
b.compile_js()
|
||||
}
|
||||
.x64 {
|
||||
b.compile_x64()
|
||||
}
|
||||
else {
|
||||
eprintln('backend not implemented `$pref.backend`')
|
||||
exit(1)
|
||||
|
@ -53,7 +57,7 @@ pub fn compile(command string, pref &pref.Preferences) {
|
|||
// v.finalize_compilation()
|
||||
}
|
||||
|
||||
fn (b mut Builder) run_compiled_executable_and_exit() {
|
||||
fn (mut b Builder) run_compiled_executable_and_exit() {
|
||||
if b.pref.is_verbose {
|
||||
println('============ running $b.pref.out_name ============')
|
||||
}
|
||||
|
@ -88,7 +92,7 @@ fn (b mut Builder) run_compiled_executable_and_exit() {
|
|||
// 'strings' => 'VROOT/vlib/strings'
|
||||
// 'installed_mod' => '~/.vmodules/installed_mod'
|
||||
// 'local_mod' => '/path/to/current/dir/local_mod'
|
||||
fn (v mut Builder) set_module_lookup_paths() {
|
||||
fn (mut v Builder) set_module_lookup_paths() {
|
||||
// Module search order:
|
||||
// 0) V test files are very commonly located right inside the folder of the
|
||||
// module, which they test. Adding the parent folder of the module folder
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
module builder
|
||||
|
||||
import (
|
||||
time
|
||||
os
|
||||
v.parser
|
||||
v.pref
|
||||
v.gen
|
||||
v.gen.js
|
||||
)
|
||||
import time
|
||||
import os
|
||||
import v.parser
|
||||
import v.pref
|
||||
import v.gen
|
||||
import v.gen.js
|
||||
|
||||
pub fn (b mut Builder) gen_js(v_files []string) string {
|
||||
pub fn (mut b Builder) gen_js(v_files []string) string {
|
||||
t0 := time.ticks()
|
||||
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
||||
b.parse_imports()
|
||||
|
@ -30,7 +28,7 @@ pub fn (b mut Builder) gen_js(v_files []string) string {
|
|||
return res
|
||||
}
|
||||
|
||||
pub fn (b mut Builder) build_js(v_files []string, out_file string) {
|
||||
pub fn (mut b Builder) build_js(v_files []string, out_file string) {
|
||||
b.out_name_js = out_file
|
||||
b.info('build_js($out_file)')
|
||||
mut f := os.create(out_file) or {
|
||||
|
@ -40,8 +38,8 @@ pub fn (b mut Builder) build_js(v_files []string, out_file string) {
|
|||
f.close()
|
||||
}
|
||||
|
||||
pub fn (b mut Builder) compile_js() {
|
||||
//TODO files << b.get_builtin_files()
|
||||
pub fn (mut b Builder) compile_js() {
|
||||
// TODO files << b.get_builtin_files()
|
||||
files := b.get_user_files()
|
||||
b.set_module_lookup_paths()
|
||||
if b.pref.is_verbose {
|
||||
|
@ -49,5 +47,5 @@ pub fn (b mut Builder) compile_js() {
|
|||
println(files)
|
||||
}
|
||||
b.build_js(files, b.pref.out_name + '.js')
|
||||
//TODO run the file
|
||||
// TODO run the file
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
module builder
|
||||
|
||||
import (
|
||||
os
|
||||
time
|
||||
)
|
||||
import os
|
||||
import time
|
||||
|
||||
fn (v &Builder) generate_hotcode_reloading_declarations() {
|
||||
/*
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
module builder
|
||||
|
||||
import (
|
||||
time
|
||||
os
|
||||
v.parser
|
||||
v.pref
|
||||
v.gen
|
||||
v.gen.x64
|
||||
)
|
||||
import time
|
||||
import os
|
||||
import v.parser
|
||||
import v.pref
|
||||
import v.gen
|
||||
import v.gen.x64
|
||||
|
||||
pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
|
||||
pub fn (mut b Builder) build_x64(v_files []string, out_file string) {
|
||||
$if !linux {
|
||||
println('v -x64 can only generate Linux binaries for now')
|
||||
println('You are not on a Linux system, so you will not ' + 'be able to run the resulting executable')
|
||||
|
@ -30,9 +28,9 @@ pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
|
|||
b.info('x64 GEN: ${gen_time}ms')
|
||||
}
|
||||
|
||||
pub fn (b mut Builder) compile_x64() {
|
||||
pub fn (mut b Builder) compile_x64() {
|
||||
// v.files << v.v_files_from_dir(os.join_path(v.pref.vlib_path,'builtin','bare'))
|
||||
files := [b.pref.path]
|
||||
files := [ b.pref.path]
|
||||
b.set_module_lookup_paths()
|
||||
b.build_x64(files, b.pref.out_name)
|
||||
}
|
|
@ -3,16 +3,14 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module checker
|
||||
|
||||
import (
|
||||
v.ast
|
||||
v.depgraph
|
||||
v.table
|
||||
v.token
|
||||
v.pref
|
||||
v.util
|
||||
v.scanner
|
||||
os
|
||||
)
|
||||
import v.ast
|
||||
import v.depgraph
|
||||
import v.table
|
||||
import v.token
|
||||
import v.pref
|
||||
import v.util
|
||||
import v.scanner
|
||||
import os
|
||||
|
||||
const (
|
||||
max_nr_errors = 300
|
||||
|
@ -46,14 +44,14 @@ pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check(ast_file ast.File) {
|
||||
pub fn (mut c Checker) check(ast_file ast.File) {
|
||||
c.file = ast_file
|
||||
for stmt in ast_file.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check2(ast_file ast.File) []scanner.Error {
|
||||
pub fn (mut c Checker) check2(ast_file ast.File) []scanner.Error {
|
||||
c.file = ast_file
|
||||
for stmt in ast_file.stmts {
|
||||
c.stmt(stmt)
|
||||
|
@ -61,7 +59,7 @@ pub fn (c mut Checker) check2(ast_file ast.File) []scanner.Error {
|
|||
return c.errors
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
||||
pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||
mut has_main_fn := false
|
||||
for file in ast_files {
|
||||
c.check(file)
|
||||
|
@ -90,7 +88,7 @@ const (
|
|||
|
||||
// do checks specific to files in main module
|
||||
// returns `true` if a main function is in the file
|
||||
fn (c mut Checker) check_file_in_main(file ast.File) bool {
|
||||
fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
||||
mut has_main_fn := false
|
||||
for stmt in file.stmts {
|
||||
match stmt {
|
||||
|
@ -122,7 +120,8 @@ fn (c mut Checker) check_file_in_main(file ast.File) bool {
|
|||
}
|
||||
if it.ctdefine.len > 0 {
|
||||
if it.return_type != table.void_type {
|
||||
c.error('only functions that do NOT return values can have `[if ${it.ctdefine}]` tags', it.pos)
|
||||
c.error('only functions that do NOT return values can have `[if ${it.ctdefine}]` tags',
|
||||
it.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +155,7 @@ fn (c mut Checker) check_file_in_main(file ast.File) bool {
|
|||
return has_main_fn
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) struct_decl(decl ast.StructDecl) {
|
||||
pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
|
||||
splitted_full_name := decl.name.split('.')
|
||||
is_builtin := splitted_full_name[0] == 'builtin'
|
||||
name := splitted_full_name.last()
|
||||
|
@ -168,28 +167,25 @@ pub fn (c mut Checker) struct_decl(decl ast.StructDecl) {
|
|||
}
|
||||
c.error('struct name must begin with capital letter', pos)
|
||||
}
|
||||
|
||||
for fi, _ in decl.fields {
|
||||
if decl.fields[fi].has_default_expr {
|
||||
c.expected_type = decl.fields[fi].typ
|
||||
field_expr_type := c.expr(decl.fields[fi].default_expr)
|
||||
if !c.table.check( field_expr_type, decl.fields[fi].typ ) {
|
||||
field_expr_type_sym := c.table.get_type_symbol( field_expr_type )
|
||||
field_type_sym := c.table.get_type_symbol( decl.fields[fi].typ )
|
||||
if !c.table.check(field_expr_type, decl.fields[fi].typ) {
|
||||
field_expr_type_sym := c.table.get_type_symbol(field_expr_type)
|
||||
field_type_sym := c.table.get_type_symbol(decl.fields[fi].typ)
|
||||
field_name := decl.fields[fi].name
|
||||
fet_name := field_expr_type_sym.name
|
||||
ft_name := field_type_sym.name
|
||||
c.error('default expression for field `${field_name}` '+
|
||||
'has type `${fet_name}`, but should be `${ft_name}`',
|
||||
decl.fields[fi].default_expr.position()
|
||||
)
|
||||
c.error('default expression for field `${field_name}` ' + 'has type `${fet_name}`, but should be `${ft_name}`',
|
||||
decl.fields[fi].default_expr.position())
|
||||
}
|
||||
}
|
||||
}
|
||||
// && (p.tok.lit[0].is_capital() || is_c || (p.builtin_mod && Sp.tok.lit in table.builtin_type_names))
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
||||
pub fn (mut c Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
||||
// typ := c.table.find_type(struct_init.typ.typ.name) or {
|
||||
// c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos)
|
||||
// panic('')
|
||||
|
@ -203,7 +199,6 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
|||
struct_init.typ = c.expected_type
|
||||
}
|
||||
type_sym := c.table.get_type_symbol(struct_init.typ)
|
||||
|
||||
// println('check struct $typ_sym.name')
|
||||
match type_sym.kind {
|
||||
.placeholder {
|
||||
|
@ -239,7 +234,8 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
|||
}
|
||||
}
|
||||
if !exists {
|
||||
c.error('unknown field `$field.name` in struct literal of type `$type_sym.name`', field.pos)
|
||||
c.error('unknown field `$field.name` in struct literal of type `$type_sym.name`',
|
||||
field.pos)
|
||||
continue
|
||||
}
|
||||
if field_name in inited_fields {
|
||||
|
@ -253,7 +249,8 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
|||
expr_type_sym := c.table.get_type_symbol(expr_type)
|
||||
field_type_sym := c.table.get_type_symbol(info_field.typ)
|
||||
if !c.table.check(expr_type, info_field.typ) {
|
||||
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$info_field.name`', field.pos)
|
||||
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$info_field.name`',
|
||||
field.pos)
|
||||
}
|
||||
struct_init.fields[i].typ = expr_type
|
||||
struct_init.fields[i].expected_type = info_field.typ
|
||||
|
@ -274,7 +271,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
|||
return struct_init.typ
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||
pub fn (mut c Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||
// println('checker: infix expr(op $infix_expr.op.str())')
|
||||
c.expected_type = table.void_type
|
||||
left_type := c.expr(infix_expr.left)
|
||||
|
@ -318,12 +315,14 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
|||
if right.kind == .array {
|
||||
right_sym := c.table.get_type_symbol(right.array_info().elem_type)
|
||||
if left.kind != right_sym.kind {
|
||||
c.error('the data type on the left of `in` does not match the array item type', infix_expr.pos)
|
||||
c.error('the data type on the left of `in` does not match the array item type',
|
||||
infix_expr.pos)
|
||||
}
|
||||
} else if right.kind == .map {
|
||||
key_sym := c.table.get_type_symbol(right.map_info().key_type)
|
||||
if left.kind != key_sym.kind {
|
||||
c.error('the data type on the left of `in` does not match the map key type', infix_expr.pos)
|
||||
c.error('the data type on the left of `in` does not match the map key type',
|
||||
infix_expr.pos)
|
||||
}
|
||||
} else if right.kind == .string {
|
||||
if left.kind != .string {
|
||||
|
@ -336,10 +335,11 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
|||
}
|
||||
if infix_expr.op in [.amp, .pipe, .xor] {
|
||||
if !left.is_int() {
|
||||
c.error('left type of `${infix_expr.op.str()}` cannot be non-integer type $left.name', infix_expr.left.position())
|
||||
}
|
||||
else if !right.is_int() {
|
||||
c.error('right type of `${infix_expr.op.str()}` cannot be non-integer type $right.name', infix_expr.right.position())
|
||||
c.error('left type of `${infix_expr.op.str()}` cannot be non-integer type $left.name',
|
||||
infix_expr.left.position())
|
||||
} else if !right.is_int() {
|
||||
c.error('right type of `${infix_expr.op.str()}` cannot be non-integer type $right.name',
|
||||
infix_expr.right.position())
|
||||
}
|
||||
}
|
||||
if infix_expr.op == .mod {
|
||||
|
@ -376,7 +376,8 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
|||
if left_type == table.void_type || right_type == table.void_type {
|
||||
return table.void_type
|
||||
}
|
||||
c.error('infix expr: cannot use `$right.name` (right expression) as `$left.name`', infix_expr.pos)
|
||||
c.error('infix expr: cannot use `$right.name` (right expression) as `$left.name`',
|
||||
infix_expr.pos)
|
||||
}
|
||||
if infix_expr.op.is_relational() {
|
||||
return table.bool_type
|
||||
|
@ -384,7 +385,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
|||
return left_type
|
||||
}
|
||||
|
||||
fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||
fn (mut c Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||
c.expected_type = table.void_type
|
||||
left_type := c.expr(assign_expr.left)
|
||||
c.expected_type = left_type
|
||||
|
@ -402,7 +403,8 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
|||
scope := c.file.scope.innermost(assign_expr.pos.pos)
|
||||
if v := scope.find_var(it.name) {
|
||||
if !v.is_mut {
|
||||
c.error('`$it.name` is immutable, declare it with `mut` to assign to it', assign_expr.pos)
|
||||
c.error('`$it.name` is immutable, declare it with `mut` to assign to it',
|
||||
assign_expr.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -410,40 +412,40 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
|||
}
|
||||
// Single side check
|
||||
match assign_expr.op {
|
||||
.assign { } // No need to do single side check for =. But here put it first for speed.
|
||||
.assign {} // No need to do single side check for =. But here put it first for speed.
|
||||
.plus_assign {
|
||||
if !left.is_number() && left_type != table.string_type && !left.is_pointer() {
|
||||
c.error('operator += not defined on left operand type `$left.name`', assign_expr.left.position())
|
||||
}
|
||||
else if !right.is_number() && right_type != table.string_type && !right.is_pointer() {
|
||||
} else if !right.is_number() && right_type != table.string_type && !right.is_pointer() {
|
||||
c.error('operator += not defined on right operand type `$right.name`', assign_expr.val.position())
|
||||
}
|
||||
}
|
||||
.minus_assign {
|
||||
if !left.is_number() && !left.is_pointer() {
|
||||
c.error('operator -= not defined on left operand type `$left.name`', assign_expr.left.position())
|
||||
}
|
||||
else if !right.is_number() && !right.is_pointer() {
|
||||
} else if !right.is_number() && !right.is_pointer() {
|
||||
c.error('operator -= not defined on right operand type `$right.name`', assign_expr.val.position())
|
||||
}
|
||||
}
|
||||
.mult_assign, .div_assign {
|
||||
if !left.is_number() {
|
||||
c.error('operator ${assign_expr.op.str()} not defined on left operand type `$left.name`', assign_expr.left.position())
|
||||
}
|
||||
else if !right.is_number() {
|
||||
c.error('operator ${assign_expr.op.str()} not defined on right operand type `$right.name`', assign_expr.val.position())
|
||||
c.error('operator ${assign_expr.op.str()} not defined on left operand type `$left.name`',
|
||||
assign_expr.left.position())
|
||||
} else if !right.is_number() {
|
||||
c.error('operator ${assign_expr.op.str()} not defined on right operand type `$right.name`',
|
||||
assign_expr.val.position())
|
||||
}
|
||||
}
|
||||
.and_assign, .or_assign, .xor_assign, .mod_assign, .left_shift_assign, .right_shift_assign {
|
||||
if !left.is_int() {
|
||||
c.error('operator ${assign_expr.op.str()} not defined on left operand type `$left.name`', assign_expr.left.position())
|
||||
}
|
||||
else if !right.is_int() {
|
||||
c.error('operator ${assign_expr.op.str()} not defined on right operand type `$right.name`', assign_expr.val.position())
|
||||
c.error('operator ${assign_expr.op.str()} not defined on left operand type `$left.name`',
|
||||
assign_expr.left.position())
|
||||
} else if !right.is_int() {
|
||||
c.error('operator ${assign_expr.op.str()} not defined on right operand type `$right.name`',
|
||||
assign_expr.val.position())
|
||||
}
|
||||
}
|
||||
else { }
|
||||
else {}
|
||||
}
|
||||
// Dual sides check (compatibility check)
|
||||
if !c.table.check(right_type, left_type) {
|
||||
|
@ -455,7 +457,7 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
|||
c.check_expr_opt_call(assign_expr.val, right_type, true)
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||
pub fn (mut c Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||
c.stmts(call_expr.or_block.stmts)
|
||||
if call_expr.is_method {
|
||||
return c.call_method(call_expr)
|
||||
|
@ -463,7 +465,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
|||
return c.call_fn(call_expr)
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
||||
pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
||||
left_type := c.expr(call_expr.left)
|
||||
call_expr.left_type = left_type
|
||||
left_type_sym := c.table.get_type_symbol(left_type)
|
||||
|
@ -496,16 +498,18 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
|||
return info.elem_type
|
||||
}
|
||||
if method := c.table.type_find_method(left_type_sym, method_name) {
|
||||
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && left_type_sym.mod != c.mod && left_type_sym.mod != '' { // method.mod != c.mod {
|
||||
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && left_type_sym.mod != c.mod &&
|
||||
left_type_sym.mod != '' { // method.mod != c.mod {
|
||||
// If a private method is called outside of the module
|
||||
// its receiver type is defined in, show an error.
|
||||
//println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
||||
// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
||||
c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos)
|
||||
}
|
||||
if method.return_type == table.void_type && method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines {
|
||||
if method.return_type == table.void_type && method.ctdefine.len > 0 && method.ctdefine !in
|
||||
c.pref.compile_defines {
|
||||
call_expr.should_be_skipped = true
|
||||
}
|
||||
nr_args := if method.args.len == 0 { 0 } else {method.args.len - 1}
|
||||
nr_args := if method.args.len == 0 { 0 } else { method.args.len - 1 }
|
||||
min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 }
|
||||
if call_expr.args.len < min_required_args {
|
||||
c.error('too few arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $min_required_args)',
|
||||
|
@ -528,7 +532,8 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
|||
}
|
||||
arg_typ := c.expr(arg.expr)
|
||||
call_expr.args[i].typ = arg_typ
|
||||
if method.is_variadic && arg_typ.flag_is(.variadic) && call_expr.args.len-1 > i {
|
||||
if method.is_variadic && arg_typ.flag_is(.variadic) && call_expr.args.len - 1 >
|
||||
i {
|
||||
c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
|
||||
}
|
||||
}
|
||||
|
@ -568,7 +573,7 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
|||
return table.void_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
||||
pub fn (mut c Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
||||
if call_expr.name == 'panic' {
|
||||
c.returns = true
|
||||
}
|
||||
|
@ -620,11 +625,9 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
|||
return table.void_type
|
||||
}
|
||||
call_expr.return_type = f.return_type
|
||||
|
||||
if f.return_type == table.void_type && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines {
|
||||
call_expr.should_be_skipped = true
|
||||
}
|
||||
|
||||
if f.is_c || call_expr.is_c || f.is_js || call_expr.is_js {
|
||||
for arg in call_expr.args {
|
||||
c.expr(arg.expr)
|
||||
|
@ -659,7 +662,7 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
|||
call_expr.args[i].typ = typ
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
arg_typ_sym := c.table.get_type_symbol(arg.typ)
|
||||
if f.is_variadic && typ.flag_is(.variadic) && call_expr.args.len-1 > i {
|
||||
if f.is_variadic && typ.flag_is(.variadic) && call_expr.args.len - 1 > i {
|
||||
c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
|
||||
}
|
||||
if !c.table.check(typ, arg.typ) {
|
||||
|
@ -683,7 +686,7 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
|||
return f.return_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check_expr_opt_call(x ast.Expr, xtype table.Type, is_return_used bool) {
|
||||
pub fn (mut c Checker) check_expr_opt_call(x ast.Expr, xtype table.Type, is_return_used bool) {
|
||||
match x {
|
||||
ast.CallExpr {
|
||||
if it.return_type.flag_is(.optional) {
|
||||
|
@ -694,7 +697,7 @@ pub fn (c mut Checker) check_expr_opt_call(x ast.Expr, xtype table.Type, is_retu
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check_or_block(call_expr mut ast.CallExpr, ret_type table.Type, is_ret_used bool) {
|
||||
pub fn (mut c Checker) check_or_block(call_expr mut ast.CallExpr, ret_type table.Type, is_ret_used bool) {
|
||||
if !call_expr.or_block.is_used {
|
||||
c.error('${call_expr.name}() returns an option, but you missed to add an `or {}` block to it',
|
||||
call_expr.pos)
|
||||
|
@ -746,34 +749,22 @@ pub fn (c mut Checker) check_or_block(call_expr mut ast.CallExpr, ret_type table
|
|||
|
||||
fn is_expr_panic_or_exit(expr ast.Expr) bool {
|
||||
match expr {
|
||||
ast.CallExpr {
|
||||
return it.name in ['panic', 'exit']
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
ast.CallExpr { return it.name in ['panic', 'exit'] }
|
||||
else { return false }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: merge to check_or_block when v can handle it
|
||||
pub fn (c mut Checker) is_last_or_block_stmt_valid(stmt ast.Stmt) bool {
|
||||
pub fn (mut c Checker) is_last_or_block_stmt_valid(stmt ast.Stmt) bool {
|
||||
return match stmt {
|
||||
ast.Return {
|
||||
true
|
||||
}
|
||||
ast.BranchStmt {
|
||||
true
|
||||
}
|
||||
ast.ExprStmt {
|
||||
true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
ast.Return { true }
|
||||
ast.BranchStmt { true }
|
||||
ast.ExprStmt { true }
|
||||
else { false }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.Type {
|
||||
pub fn (mut c Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.Type {
|
||||
typ := c.expr(selector_expr.expr)
|
||||
if typ == table.void_type_idx {
|
||||
c.error('unknown selector expression', selector_expr.pos)
|
||||
|
@ -801,7 +792,7 @@ pub fn (c mut Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.T
|
|||
}
|
||||
|
||||
// TODO: non deferred
|
||||
pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
|
||||
pub fn (mut c Checker) return_stmt(return_stmt mut ast.Return) {
|
||||
c.expected_type = c.fn_return_type
|
||||
if return_stmt.exprs.len > 0 && c.fn_return_type == table.void_type {
|
||||
c.error('too many arguments to return, current function does not return anything',
|
||||
|
@ -842,12 +833,13 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
|
|||
got_typ_sym := c.table.get_type_symbol(got_typ)
|
||||
exp_typ_sym := c.table.get_type_symbol(exp_typ)
|
||||
pos := return_stmt.exprs[i].position()
|
||||
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument', pos)
|
||||
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument',
|
||||
pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) enum_decl(decl ast.EnumDecl) {
|
||||
pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
||||
for field in decl.fields {
|
||||
if field.has_expr {
|
||||
match field.expr {
|
||||
|
@ -871,13 +863,14 @@ pub fn (c mut Checker) enum_decl(decl ast.EnumDecl) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
||||
pub fn (mut c Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
||||
c.expected_type = table.none_type // TODO a hack to make `x := if ... work`
|
||||
// check variablename for beginning with capital letter 'Abc'
|
||||
for ident in assign_stmt.left {
|
||||
is_decl := assign_stmt.op == .decl_assign
|
||||
if is_decl && scanner.contains_capital(ident.name) {
|
||||
c.error('variable names cannot contain uppercase letters, use snake_case instead', ident.pos)
|
||||
c.error('variable names cannot contain uppercase letters, use snake_case instead',
|
||||
ident.pos)
|
||||
} else if is_decl && ident.kind != .blank_ident {
|
||||
if ident.name.starts_with('__') {
|
||||
c.error('variable names cannot start with `__`', ident.pos)
|
||||
|
@ -888,9 +881,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
|||
// multi return
|
||||
match assign_stmt.right[0] {
|
||||
ast.CallExpr {}
|
||||
else {
|
||||
c.error('assign_stmt: expected call', assign_stmt.pos)
|
||||
}
|
||||
else { c.error('assign_stmt: expected call', assign_stmt.pos) }
|
||||
}
|
||||
right_type := c.expr(assign_stmt.right[0])
|
||||
right_type_sym := c.table.get_type_symbol(right_type)
|
||||
|
@ -969,7 +960,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
|||
// c.assigned_var_name = ''
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
|
||||
pub fn (mut c Checker) array_init(array_init mut ast.ArrayInit) table.Type {
|
||||
// println('checker: array init $array_init.pos.line_nr $c.file.path')
|
||||
mut elem_type := table.void_type
|
||||
// []string - was set in parser
|
||||
|
@ -1056,15 +1047,13 @@ fn const_int_value(cfield ast.ConstField) ?int {
|
|||
|
||||
fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral {
|
||||
match cfield.expr {
|
||||
ast.IntegerLiteral {
|
||||
return *it
|
||||
}
|
||||
ast.IntegerLiteral { return *it }
|
||||
else {}
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
fn (c mut Checker) stmt(node ast.Stmt) {
|
||||
fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
// c.expected_type = table.void_type
|
||||
match mut node {
|
||||
ast.AssertStmt {
|
||||
|
@ -1151,8 +1140,8 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
|||
c.expected_type = table.void_type
|
||||
c.fn_return_type = it.return_type
|
||||
c.stmts(it.stmts)
|
||||
if !it.is_c && !it.is_js && !it.no_body && it.return_type != table.void_type && !c.returns &&
|
||||
!(it.name in ['panic', 'exit']) {
|
||||
if !it.is_c && !it.is_js && !it.no_body && it.return_type != table.void_type &&
|
||||
!c.returns && !(it.name in ['panic', 'exit']) {
|
||||
c.error('missing return at end of function `$it.name`', it.pos)
|
||||
}
|
||||
c.returns = false
|
||||
|
@ -1198,12 +1187,8 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
|||
sym := c.table.get_type_symbol(typ)
|
||||
if it.key_var.len > 0 {
|
||||
key_type := match sym.kind {
|
||||
.map {
|
||||
sym.map_info().key_type
|
||||
}
|
||||
else {
|
||||
table.int_type
|
||||
}
|
||||
.map { sym.map_info().key_type }
|
||||
else { table.int_type }
|
||||
}
|
||||
it.key_type = key_type
|
||||
scope.update_var_type(it.key_var, key_type)
|
||||
|
@ -1233,7 +1218,6 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
|||
c.mod = it.name
|
||||
c.is_builtin_mod = it.name == 'builtin'
|
||||
}
|
||||
|
||||
// ast.GlobalDecl {}
|
||||
ast.Return {
|
||||
c.returns = true
|
||||
|
@ -1259,7 +1243,7 @@ fn is_call_expr(expr ast.Expr) bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn (c mut Checker) stmts(stmts []ast.Stmt) {
|
||||
fn (mut c Checker) stmts(stmts []ast.Stmt) {
|
||||
c.expected_type = table.void_type
|
||||
for stmt in stmts {
|
||||
c.stmt(stmt)
|
||||
|
@ -1267,7 +1251,7 @@ fn (c mut Checker) stmts(stmts []ast.Stmt) {
|
|||
c.expected_type = table.void_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||
pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||
match mut node {
|
||||
ast.ArrayInit {
|
||||
return c.array_init(mut it)
|
||||
|
@ -1418,7 +1402,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
|||
return table.void_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
||||
pub fn (mut c Checker) ident(ident mut ast.Ident) table.Type {
|
||||
if ident.name == c.var_decl_name { // c.checked_ident {
|
||||
c.error('unresolved: `$ident.name`', ident.pos)
|
||||
return table.void_type
|
||||
|
@ -1524,7 +1508,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
|||
return table.void_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
|
||||
pub fn (mut c Checker) match_expr(node mut ast.MatchExpr) table.Type {
|
||||
node.is_expr = c.expected_type != table.void_type
|
||||
node.expected_type = c.expected_type
|
||||
cond_type := c.expr(node.cond)
|
||||
|
@ -1583,15 +1567,9 @@ fn (mut c Checker) match_exprs(node mut ast.MatchExpr, type_sym table.TypeSymbol
|
|||
for expr in branch.exprs {
|
||||
mut key := ''
|
||||
match expr {
|
||||
ast.Type {
|
||||
key = c.table.type_to_str(it.typ)
|
||||
}
|
||||
ast.EnumVal {
|
||||
key = it.val
|
||||
}
|
||||
else {
|
||||
key = expr.str()
|
||||
}
|
||||
ast.Type { key = c.table.type_to_str(it.typ) }
|
||||
ast.EnumVal { key = it.val }
|
||||
else { key = expr.str() }
|
||||
}
|
||||
val := if key in branch_exprs { branch_exprs[key] } else { 0 }
|
||||
if val == 1 {
|
||||
|
@ -1646,7 +1624,7 @@ fn (mut c Checker) match_exprs(node mut ast.MatchExpr, type_sym table.TypeSymbol
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
||||
pub fn (mut c Checker) if_expr(node mut ast.IfExpr) table.Type {
|
||||
if c.expected_type != table.void_type {
|
||||
// | c.assigned_var_name != '' {
|
||||
// sym := c.table.get_type_symbol(c.expected_type)
|
||||
|
@ -1656,7 +1634,8 @@ pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
|||
node.typ = table.void_type
|
||||
for i, branch in node.branches {
|
||||
if branch.cond is ast.ParExpr {
|
||||
c.error('unnecessary `()` in an if condition. use `if expr {` instead of `if (expr) {`.', branch.pos)
|
||||
c.error('unnecessary `()` in an if condition. use `if expr {` instead of `if (expr) {`.',
|
||||
branch.pos)
|
||||
}
|
||||
typ := c.expr(branch.cond)
|
||||
if i < node.branches.len - 1 || !node.has_else {
|
||||
|
@ -1686,7 +1665,7 @@ pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
|||
return table.bool_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
||||
pub fn (mut c Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
||||
/*
|
||||
match node.expr {
|
||||
ast.IdentVar {
|
||||
|
@ -1694,7 +1673,7 @@ pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
|||
}
|
||||
else {}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
typ := c.expr(node.expr)
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
// if !typ.is_number() {
|
||||
|
@ -1705,7 +1684,7 @@ pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
|||
return typ
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
|
||||
pub fn (mut c Checker) index_expr(node mut ast.IndexExpr) table.Type {
|
||||
typ := c.expr(node.left)
|
||||
node.left_type = typ
|
||||
mut is_range := false // TODO is_range := node.index is ast.RangeExpr
|
||||
|
@ -1754,7 +1733,7 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
|
|||
// `.green` or `Color.green`
|
||||
// If a short form is used, `expected_type` needs to be an enum
|
||||
// with this value.
|
||||
pub fn (c mut Checker) enum_val(node mut ast.EnumVal) table.Type {
|
||||
pub fn (mut c Checker) enum_val(node mut ast.EnumVal) table.Type {
|
||||
typ_idx := if node.enum_name == '' {
|
||||
c.expected_type.idx()
|
||||
} else { //
|
||||
|
@ -1781,7 +1760,7 @@ pub fn (c mut Checker) enum_val(node mut ast.EnumVal) table.Type {
|
|||
return typ
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) map_init(node mut ast.MapInit) table.Type {
|
||||
pub fn (mut c Checker) map_init(node mut ast.MapInit) table.Type {
|
||||
// `x ;= map[string]string` - set in parser
|
||||
if node.typ != 0 {
|
||||
info := c.table.get_type_symbol(node.typ).map_info()
|
||||
|
@ -1819,19 +1798,19 @@ pub fn (c mut Checker) map_init(node mut ast.MapInit) table.Type {
|
|||
return map_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) warn(s string, pos token.Position) {
|
||||
pub fn (mut c Checker) warn(s string, pos token.Position) {
|
||||
allow_warnings := !c.pref.is_prod // allow warnings only in dev builds
|
||||
c.warn_or_error(s, pos, allow_warnings) // allow warnings only in dev builds
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) error(message string, pos token.Position) {
|
||||
pub fn (mut c Checker) error(message string, pos token.Position) {
|
||||
if c.pref.is_verbose {
|
||||
print_backtrace()
|
||||
}
|
||||
c.warn_or_error(message, pos, false)
|
||||
}
|
||||
|
||||
fn (c mut Checker) warn_or_error(message string, pos token.Position, warn bool) {
|
||||
fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool) {
|
||||
// add backtrace to issue struct, how?
|
||||
// if c.pref.is_verbose {
|
||||
// print_backtrace()
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import (
|
||||
v.table
|
||||
v.doc
|
||||
)
|
||||
import v.table
|
||||
import v.doc
|
||||
|
||||
fn test_vdoc() {
|
||||
table := table.new_table()
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module eval
|
||||
|
||||
import (
|
||||
v.ast
|
||||
v.checker
|
||||
v.table
|
||||
v.pref
|
||||
)
|
||||
import v.ast
|
||||
import v.checker
|
||||
import v.table
|
||||
import v.pref
|
||||
|
||||
pub type Object = int | string
|
||||
|
||||
|
@ -23,7 +21,7 @@ pub struct Var {
|
|||
value Object
|
||||
}
|
||||
|
||||
pub fn (e mut Eval) eval(file ast.File, table &table.Table) string {
|
||||
pub fn (mut e Eval) eval(file ast.File, table &table.Table) string {
|
||||
vpref := &pref.Preferences{}
|
||||
e.table = table
|
||||
mut res := ''
|
||||
|
@ -36,29 +34,24 @@ pub fn (e mut Eval) eval(file ast.File, table &table.Table) string {
|
|||
|
||||
fn print_object(o Object) {
|
||||
match o {
|
||||
int {
|
||||
println(it)
|
||||
}
|
||||
else {
|
||||
println('unknown object')
|
||||
}
|
||||
int { println(it) }
|
||||
else { println('unknown object') }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (o Object) str() string {
|
||||
match o {
|
||||
int {
|
||||
return it.str()
|
||||
}
|
||||
else {
|
||||
println('unknown object')
|
||||
}
|
||||
int { return it.str() }
|
||||
else { println('unknown object') }
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
fn (e mut Eval) stmt(node ast.Stmt) string {
|
||||
fn (mut e Eval) stmt(node ast.Stmt) string {
|
||||
match node {
|
||||
ast.AssignStmt {
|
||||
// TODO; replaced VarDecl
|
||||
}
|
||||
ast.ExprStmt {
|
||||
o := e.expr(it.expr)
|
||||
print('out: ')
|
||||
|
@ -68,9 +61,6 @@ fn (e mut Eval) stmt(node ast.Stmt) string {
|
|||
// ast.StructDecl {
|
||||
// println('s decl')
|
||||
// }
|
||||
ast.AssignStmt {
|
||||
// TODO; replaced VarDecl
|
||||
}
|
||||
// ast.VarDecl {
|
||||
// e.vars[it.name] = Var{
|
||||
// value: e.expr(it.expr)
|
||||
|
@ -81,7 +71,7 @@ fn (e mut Eval) stmt(node ast.Stmt) string {
|
|||
return '>>'
|
||||
}
|
||||
|
||||
fn (e mut Eval) expr(node ast.Expr) Object {
|
||||
fn (mut e Eval) expr(node ast.Expr) Object {
|
||||
match node {
|
||||
ast.IntegerLiteral {
|
||||
return it.val
|
||||
|
@ -98,12 +88,8 @@ fn (e mut Eval) expr(node ast.Expr) Object {
|
|||
left := e.expr(it.left) as int
|
||||
right := e.expr(it.right) as int
|
||||
match it.op {
|
||||
.plus {
|
||||
return left + right
|
||||
}
|
||||
.mul {
|
||||
return left * right
|
||||
}
|
||||
.plus { return left + right }
|
||||
.mul { return left * right }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
|
133
vlib/v/fmt/fmt.v
133
vlib/v/fmt/fmt.v
|
@ -106,7 +106,7 @@ fn (mut f Fmt) imports(imports []ast.Import) {
|
|||
imp_stmt_str := f.imp_stmt_str(imports[0])
|
||||
f.out_imports.writeln('import ${imp_stmt_str}\n')
|
||||
} else if imports.len > 1 {
|
||||
*/
|
||||
*/
|
||||
// f.out_imports.writeln('import (')
|
||||
for imp in imports {
|
||||
if !(imp.mod in f.used_imports) {
|
||||
|
@ -247,23 +247,7 @@ fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||
}
|
||||
}
|
||||
ast.FnDecl {
|
||||
// println('$it.name find_comment($it.pos.line_nr)')
|
||||
// f.find_comment(it.pos.line_nr)
|
||||
s := it.str(f.table)
|
||||
// f.write(it.str(f.table))
|
||||
f.write(s.replace(f.cur_mod + '.', '')) // `Expr` instead of `ast.Expr` in mod ast
|
||||
if !it.is_c && !it.is_js {
|
||||
f.writeln(' {')
|
||||
f.stmts(it.stmts)
|
||||
f.writeln('}\n')
|
||||
} else {
|
||||
f.writeln('\n')
|
||||
}
|
||||
// Mark all function's used type so that they are not removed from imports
|
||||
for arg in it.args {
|
||||
f.mark_types_module_as_used(arg.typ)
|
||||
}
|
||||
f.mark_types_module_as_used(it.return_type)
|
||||
f.fn_decl(it)
|
||||
}
|
||||
ast.ForCStmt {
|
||||
f.write('for ')
|
||||
|
@ -320,6 +304,11 @@ fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||
f.expr(it.expr)
|
||||
}
|
||||
}
|
||||
ast.GoStmt {
|
||||
f.write('go ')
|
||||
f.expr(it.call_expr)
|
||||
f.writeln('')
|
||||
}
|
||||
ast.GotoLabel {
|
||||
f.writeln('$it.name:')
|
||||
}
|
||||
|
@ -374,12 +363,6 @@ fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||
f.stmts(it.stmts)
|
||||
f.writeln('}')
|
||||
}
|
||||
else {
|
||||
eprintln('fmt stmt: unhandled node ' + typeof(node))
|
||||
if typeof(node) != 'unknown v.ast.Expr' {
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,15 +443,18 @@ fn (f &Fmt) type_to_str(t table.Type) string {
|
|||
mut res := f.table.type_to_str(t)
|
||||
// type_ptr => &type
|
||||
if res.ends_with('_ptr') {
|
||||
res = res[0 .. res.len - 4]
|
||||
res = res[0..res.len - 4]
|
||||
start_pos := 2 * res.count('[]')
|
||||
res = res[0 .. start_pos] + '&' + res[start_pos .. res.len]
|
||||
res = res[0..start_pos] + '&' + res[start_pos..res.len]
|
||||
}
|
||||
return res.replace(f.cur_mod + '.', '')
|
||||
}
|
||||
|
||||
fn (mut f Fmt) expr(node ast.Expr) {
|
||||
match node {
|
||||
ast.AnonFn {
|
||||
f.fn_decl(it.decl)
|
||||
}
|
||||
ast.ArrayInit {
|
||||
if it.exprs.len == 0 && it.typ != 0 && it.typ != table.void_type {
|
||||
// `x := []string`
|
||||
|
@ -478,25 +464,29 @@ fn (mut f Fmt) expr(node ast.Expr) {
|
|||
// type_sym := f.table.get_type_symbol(it.typ)
|
||||
f.write('[')
|
||||
mut inc_indent := false
|
||||
mut line_nr := node.position().line_nr // to have the same newlines between array elements
|
||||
mut last_line_nr := node.position().line_nr // to have the same newlines between array elements
|
||||
for i, expr in it.exprs {
|
||||
pos := expr.position()
|
||||
if i == 0 && line_nr < pos.line_nr {
|
||||
f.writeln('')
|
||||
line_nr := expr.position().line_nr
|
||||
if last_line_nr < line_nr {
|
||||
if !inc_indent {
|
||||
f.indent++
|
||||
inc_indent = true
|
||||
}
|
||||
if i > 0 && it.exprs.len > 1 {
|
||||
f.wrap_long_line()
|
||||
f.writeln('')
|
||||
}
|
||||
is_new_line := last_line_nr < line_nr || f.wrap_long_line()
|
||||
if !is_new_line && i > 0 {
|
||||
f.write(' ')
|
||||
}
|
||||
f.expr(expr)
|
||||
if line_nr < pos.line_nr {
|
||||
// Previous element was on a different line, add a newline
|
||||
if i == it.exprs.len - 1 {
|
||||
if is_new_line {
|
||||
f.writeln('')
|
||||
} else if i < it.exprs.len - 1 {
|
||||
f.write(', ')
|
||||
}
|
||||
line_nr = pos.line_nr
|
||||
} else {
|
||||
f.write(',')
|
||||
}
|
||||
last_line_nr = line_nr
|
||||
}
|
||||
if inc_indent {
|
||||
f.indent--
|
||||
|
@ -541,6 +531,14 @@ fn (mut f Fmt) expr(node ast.Expr) {
|
|||
ast.CharLiteral {
|
||||
f.write('`$it.val`')
|
||||
}
|
||||
ast.ConcatExpr {
|
||||
for i, val in it.vals {
|
||||
if i != 0 {
|
||||
f.write(' + ')
|
||||
}
|
||||
f.expr(val)
|
||||
}
|
||||
}
|
||||
ast.EnumVal {
|
||||
name := short_module(it.enum_name)
|
||||
f.write(name + '.' + it.val)
|
||||
|
@ -563,6 +561,10 @@ fn (mut f Fmt) expr(node ast.Expr) {
|
|||
}
|
||||
}
|
||||
}
|
||||
ast.IfGuardExpr {
|
||||
f.write(it.var_name + ' := ')
|
||||
f.expr(it.expr)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
f.expr(it.left)
|
||||
f.write(' $it.op.str() ')
|
||||
|
@ -606,9 +608,10 @@ fn (mut f Fmt) expr(node ast.Expr) {
|
|||
ast.None {
|
||||
f.write('none')
|
||||
}
|
||||
ast.IfGuardExpr {
|
||||
f.write(it.var_name + ' := ')
|
||||
f.expr(it.expr)
|
||||
ast.OrExpr {
|
||||
// shouldn't happen, an or expression
|
||||
// is always linked to a call expr
|
||||
panic('fmt: OrExpr should to linked to CallExpr')
|
||||
}
|
||||
ast.ParExpr {
|
||||
f.write('(')
|
||||
|
@ -643,7 +646,7 @@ fn (mut f Fmt) expr(node ast.Expr) {
|
|||
f.write(')')
|
||||
}
|
||||
ast.StringLiteral {
|
||||
if it.val.contains("'") {
|
||||
if it.val.contains("'") && !it.val.contains('"') {
|
||||
f.write('"$it.val"')
|
||||
} else {
|
||||
f.write("'$it.val'")
|
||||
|
@ -708,23 +711,19 @@ fn (mut f Fmt) expr(node ast.Expr) {
|
|||
f.expr(it.expr)
|
||||
f.write(')')
|
||||
}
|
||||
else {
|
||||
eprintln('fmt expr: unhandled node ' + typeof(node))
|
||||
if typeof(node) != 'unknown v.ast.Expr' {
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut f Fmt) wrap_long_line() {
|
||||
if f.line_len > max_len {
|
||||
fn (mut f Fmt) wrap_long_line() bool {
|
||||
if f.line_len <= max_len {
|
||||
return false
|
||||
}
|
||||
if f.out.buf[f.out.buf.len - 1] == ` ` {
|
||||
f.out.go_back(1)
|
||||
}
|
||||
f.write('\n' + tabs[f.indent + 1])
|
||||
f.line_len = 0
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fn (mut f Fmt) call_args(args []ast.CallArg) {
|
||||
|
@ -743,7 +742,7 @@ fn (mut f Fmt) call_args(args []ast.CallArg) {
|
|||
}
|
||||
|
||||
fn (mut f Fmt) or_expr(or_block ast.OrExpr) {
|
||||
if or_block.stmts.len > 0 {
|
||||
if or_block.is_used {
|
||||
f.writeln(' or {')
|
||||
f.stmts(or_block.stmts)
|
||||
f.write('}')
|
||||
|
@ -772,9 +771,32 @@ fn (mut f Fmt) comment(node ast.Comment) {
|
|||
f.writeln(line)
|
||||
f.empty_line = false
|
||||
}
|
||||
f.empty_line = true
|
||||
f.writeln('*/')
|
||||
}
|
||||
|
||||
fn (mut f Fmt) fn_decl(node ast.FnDecl) {
|
||||
// println('$it.name find_comment($it.pos.line_nr)')
|
||||
// f.find_comment(it.pos.line_nr)
|
||||
s := node.str(f.table)
|
||||
f.write(s.replace(f.cur_mod + '.', '')) // `Expr` instead of `ast.Expr` in mod ast
|
||||
if !node.is_c && !node.is_js {
|
||||
f.writeln(' {')
|
||||
f.stmts(node.stmts)
|
||||
f.write('}')
|
||||
if !node.is_anon {
|
||||
f.writeln('\n')
|
||||
}
|
||||
} else {
|
||||
f.writeln('\n')
|
||||
}
|
||||
// Mark all function's used type so that they are not removed from imports
|
||||
for arg in node.args {
|
||||
f.mark_types_module_as_used(arg.typ)
|
||||
}
|
||||
f.mark_types_module_as_used(node.return_type)
|
||||
}
|
||||
|
||||
// foo.bar.fn() => bar.fn()
|
||||
fn short_module(name string) string {
|
||||
if !name.contains('.') {
|
||||
|
@ -822,8 +844,8 @@ fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
|||
|
||||
fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
||||
if node.is_method {
|
||||
match node.left {
|
||||
ast.Ident {
|
||||
if node.left is ast.Ident {
|
||||
it := node.left as ast.Ident
|
||||
// `time.now()` without `time imported` is processed as a method call with `time` being
|
||||
// a `node.left` expression. Import `time` automatically.
|
||||
// TODO fetch all available modules
|
||||
|
@ -840,8 +862,6 @@ fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
|||
// }
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
f.expr(node.left)
|
||||
f.write('.' + node.name + '(')
|
||||
f.call_args(node.args)
|
||||
|
@ -882,6 +902,9 @@ fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
|||
single_line = false
|
||||
break
|
||||
}
|
||||
} else if stmt is ast.Comment {
|
||||
single_line = false
|
||||
break
|
||||
}
|
||||
}
|
||||
for i, branch in it.branches {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import (
|
||||
os
|
||||
term
|
||||
benchmark
|
||||
v.ast
|
||||
v.fmt
|
||||
v.parser
|
||||
v.table
|
||||
v.pref
|
||||
)
|
||||
import os
|
||||
import term
|
||||
import benchmark
|
||||
import v.ast
|
||||
import v.fmt
|
||||
import v.parser
|
||||
import v.table
|
||||
import v.pref
|
||||
|
||||
const (
|
||||
error_missing_vexe = 1
|
||||
|
@ -45,7 +43,9 @@ fn test_fmt() {
|
|||
continue
|
||||
}
|
||||
table := table.new_table()
|
||||
file_ast := parser.parse_file(ipath, table, .parse_comments, &pref.Preferences{}, &ast.Scope{parent: 0})
|
||||
file_ast := parser.parse_file(ipath, table, .parse_comments, &pref.Preferences{}, &ast.Scope{
|
||||
parent: 0
|
||||
})
|
||||
result_ocontent := fmt.fmt(file_ast, table)
|
||||
if expected_ocontent != result_ocontent {
|
||||
fmt_bench.fail()
|
||||
|
@ -54,7 +54,7 @@ fn test_fmt() {
|
|||
eprintln('>> sorry, but no working "diff" CLI command can be found')
|
||||
continue
|
||||
}
|
||||
vfmt_result_file := os.join_path(tmpfolder,'vfmt_run_over_${ifilename}')
|
||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_${ifilename}')
|
||||
os.write_file(vfmt_result_file, result_ocontent)
|
||||
os.system('$diff_cmd --minimal --text --unified=2 --show-function-line="fn " "$opath" "$vfmt_result_file"')
|
||||
continue
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import (
|
||||
os
|
||||
term
|
||||
benchmark
|
||||
v.ast
|
||||
v.fmt
|
||||
v.parser
|
||||
v.table
|
||||
v.pref
|
||||
)
|
||||
import os
|
||||
import term
|
||||
import benchmark
|
||||
import v.ast
|
||||
import v.fmt
|
||||
import v.parser
|
||||
import v.table
|
||||
import v.pref
|
||||
|
||||
const (
|
||||
error_missing_vexe = 1
|
||||
|
@ -47,7 +45,9 @@ fn test_fmt() {
|
|||
continue
|
||||
}
|
||||
table := table.new_table()
|
||||
file_ast := parser.parse_file(ipath, table, .parse_comments, &pref.Preferences{}, &ast.Scope{parent: 0})
|
||||
file_ast := parser.parse_file(ipath, table, .parse_comments, &pref.Preferences{}, &ast.Scope{
|
||||
parent: 0
|
||||
})
|
||||
result_ocontent := fmt.fmt(file_ast, table)
|
||||
if expected_ocontent != result_ocontent {
|
||||
fmt_bench.fail()
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
fn has_anon_fn() {
|
||||
an_fn := fn () {
|
||||
println('Hello there !')
|
||||
}
|
||||
an_fn_w_param := fn (s string) {
|
||||
println('I received $s')
|
||||
}
|
||||
an_fn_w_multi_params := fn (s1, s2, s3 string) {
|
||||
println('I received $s1, $s2, $s3')
|
||||
}
|
||||
an_fn_w_multi_params2 := fn (s string, i int) {
|
||||
println('I received $s, $i')
|
||||
}
|
||||
fn_w_var_args := fn (ss ...string) {
|
||||
for s in ss {
|
||||
println('yo $s')
|
||||
}
|
||||
}
|
||||
an_fn()
|
||||
an_fn_w_param('a gift')
|
||||
an_fn_w_multi_params('one', 'two', 'three')
|
||||
an_fn_w_multi_params2('one', 1)
|
||||
fn_w_var_args('one arg', 'two args', 'three args')
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
fn has_anon_fn() {
|
||||
an_fn := fn() {
|
||||
println('Hello there !')
|
||||
}
|
||||
an_fn_w_param := fn ( s string )
|
||||
{
|
||||
println('I received $s')
|
||||
}
|
||||
an_fn_w_multi_params := fn (s1, s2, s3 string) {
|
||||
println('I received $s1, $s2, $s3')
|
||||
}
|
||||
an_fn_w_multi_params2 :=fn (s string, i int) {
|
||||
println('I received $s, $i')
|
||||
}
|
||||
fn_w_var_args := fn (ss ...string) {
|
||||
for s in ss {
|
||||
println('yo $s')
|
||||
}
|
||||
} an_fn()
|
||||
an_fn_w_param('a gift') an_fn_w_multi_params('one', 'two', 'three')
|
||||
an_fn_w_multi_params2( 'one', 1)
|
||||
fn_w_var_args('one arg', 'two args', 'three args')
|
||||
}
|
|
@ -5,8 +5,9 @@ fn make_flag(a, b, c string) string {
|
|||
fn main() {
|
||||
// Set up flags
|
||||
expected_flags := [
|
||||
make_flag('solaris', '-L', '/opt/local/lib')
|
||||
make_flag('darwin', '-framework', 'Cocoa')
|
||||
make_flag('solaris', '-L', '/opt/local/lib'),
|
||||
make_flag('darwin', '-framework', 'Cocoa'),
|
||||
make_flag('windows', '-l', 'gdi32')
|
||||
]
|
||||
_ := expected_flags
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
fn fn_contains_index_expr() {
|
||||
arr := [1, 2, 3, 4, 5]
|
||||
a := 1 in arr[0..]
|
||||
b := 1 in arr[..2]
|
||||
c := 1 in arr[1..3]
|
||||
_ := a
|
||||
_ := 1 in arr[..2]
|
||||
_ := 1 in arr[1..3]
|
||||
d := arr[2]
|
||||
e := arr[2..]
|
||||
f := arr[..2]
|
||||
g := arr[1..3]
|
||||
_ := d
|
||||
_ := arr[2..]
|
||||
_ := arr[..2]
|
||||
_ := arr[1..3]
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
fn fn_contains_index_expr() {
|
||||
arr := [1, 2, 3, 4, 5]
|
||||
a := 1 in arr[ 0.. ]
|
||||
b := 1 in arr[ ..2 ]
|
||||
c := 1 in arr[1..3]
|
||||
_ := a
|
||||
_ := 1 in arr[ ..2 ]
|
||||
_ := 1 in arr[1..3]
|
||||
d := arr[2]
|
||||
e := arr[2 ..]
|
||||
f := arr[.. 2 ]
|
||||
g := arr[ 1 .. 3]
|
||||
_ := d
|
||||
_ := arr[2 ..]
|
||||
_ := arr[.. 2 ]
|
||||
_ := arr[ 1 .. 3]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
fn test_as() {
|
||||
a := sum_expr() as Bar
|
||||
_ := a
|
||||
}
|
||||
|
||||
fn test_cast() {
|
||||
f := f32(0)
|
||||
_ := f32(0)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
fn test_as() {
|
||||
a := sum_expr() as Bar
|
||||
_ := a
|
||||
}
|
||||
|
||||
fn test_cast() {
|
||||
f := f32(0)
|
||||
_ := f32(0)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
fn concatenation_of_strings() {
|
||||
_ := 'Simple' + 'Concat'
|
||||
_ := 'Hello' + ' ' + 'World' + '!'
|
||||
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" +
|
||||
' ' + 'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fn concatenation_of_strings() {
|
||||
_ := 'Simple' + 'Concat'
|
||||
_ := 'Hello'
|
||||
+ ' ' +
|
||||
'World' + '!'
|
||||
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" + ' ' + 'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
|
||||
}
|
|
@ -8,5 +8,5 @@ fn fn_with_if_else() {
|
|||
}
|
||||
|
||||
fn fn_with_if_else_oneline() {
|
||||
x := if true { 1 } else { 2 }
|
||||
_ := if true { 1 } else { 2 }
|
||||
}
|
||||
|
|
|
@ -6,5 +6,5 @@ fn fn_with_if_else() {
|
|||
}
|
||||
|
||||
fn fn_with_if_else_oneline() {
|
||||
x := if true { 1 } else { 2 }
|
||||
_ := if true { 1 } else { 2 }
|
||||
}
|
||||
|
|
|
@ -2,6 +2,21 @@ const (
|
|||
pi = 3.14
|
||||
phi = 1.618
|
||||
eulers = 2.7182
|
||||
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
|
||||
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
|
||||
one_line_supported = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
|
||||
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
|
||||
another_const = [
|
||||
'a', 'b',
|
||||
'c', 'd', 'e',
|
||||
'f'
|
||||
]
|
||||
)
|
||||
|
||||
const (
|
||||
i_am_a_very_long_constant_name_so_i_stand_alone_and_my_length_is_over_90_characters = [
|
||||
'testforit'
|
||||
]
|
||||
)
|
||||
|
||||
pub const (
|
||||
|
|
|
@ -2,8 +2,22 @@ const (
|
|||
pi=3.14
|
||||
phi=1.618
|
||||
eulers=2.7182
|
||||
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
|
||||
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
|
||||
one_line_supported = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd', 'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
|
||||
another_const = [
|
||||
'a', 'b'
|
||||
'c', 'd', 'e'
|
||||
'f'
|
||||
]
|
||||
)
|
||||
|
||||
const (
|
||||
i_am_a_very_long_constant_name_so_i_stand_alone_and_my_length_is_over_90_characters = ['testforit']
|
||||
)
|
||||
|
||||
pub const (
|
||||
i_am_pub_const=true
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
fn my_thread() {
|
||||
println('yo')
|
||||
}
|
||||
|
||||
fn my_thread_with_params(s string) {
|
||||
println(s)
|
||||
}
|
||||
|
||||
fn my_fn_calling_threads() {
|
||||
go my_thread()
|
||||
go my_thread_with_params('yay')
|
||||
go my_thread_with_params('nono')
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
fn my_thread() {
|
||||
println('yo')
|
||||
}
|
||||
|
||||
fn my_thread_with_params(s string)
|
||||
{
|
||||
println(s)
|
||||
}
|
||||
|
||||
fn my_fn_calling_threads () {
|
||||
go my_thread()
|
||||
go my_thread_with_params('yay')
|
||||
|
||||
go
|
||||
my_thread_with_params('nono')
|
||||
}
|
|
@ -9,9 +9,24 @@ fn match_expr() {
|
|||
|
||||
fn match_expr_assignment() {
|
||||
a := 20
|
||||
b := match a {
|
||||
_ := match a {
|
||||
10 { 10 }
|
||||
5 { 5 }
|
||||
else { 2 }
|
||||
}
|
||||
}
|
||||
|
||||
fn match_branch_comment() {
|
||||
a := 1
|
||||
match a {
|
||||
1 {
|
||||
println('1')
|
||||
}
|
||||
2 {
|
||||
println('2')
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,24 @@ fn match_expr() {
|
|||
|
||||
fn match_expr_assignment() {
|
||||
a := 20
|
||||
b := match a {
|
||||
_ := match a {
|
||||
10 { 10 }
|
||||
5 { 5 }
|
||||
else { 2 }
|
||||
}
|
||||
}
|
||||
|
||||
fn match_branch_comment() {
|
||||
a := 1
|
||||
match a {
|
||||
1 { println('1') }
|
||||
2 {
|
||||
println('2')
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,16 @@ that is on multiple lines
|
|||
*/
|
||||
fn main() {
|
||||
println('hello')
|
||||
/*
|
||||
this comment also
|
||||
has mutliple lines
|
||||
but it's difference
|
||||
is that it is indented !
|
||||
*/
|
||||
if true {
|
||||
/*
|
||||
this one is even more
|
||||
indented !
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
fn main() {
|
||||
'Hello world !'
|
||||
'This is correct !'
|
||||
"It's okay"
|
||||
'This is "too"'
|
||||
// TODO
|
||||
// 'I\'m not correctly formatted' => "I'm not correctly formatted"
|
||||
// "\"Everything on the internet is true\" - Albert Einstein, 1965" => '"Everything on the internet is true" - Albert Einstein, 1965'
|
||||
'I\'m out of idea "_"'
|
||||
// "Definitely out \":'(\"" => 'Definitely out ":\'("'
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fn main() {
|
||||
"Hello world !"
|
||||
'This is correct !'
|
||||
"It's okay"
|
||||
'This is "too"'
|
||||
// TODO
|
||||
// 'I\'m not correctly formatted' => "I'm not correctly formatted"
|
||||
// "\"Everything on the internet is true\" - Albert Einstein, 1965" => '"Everything on the internet is true" - Albert Einstein, 1965'
|
||||
'I\'m out of idea "_"'
|
||||
// "Definitely out \":'(\"" => 'Definitely out ":\'("'
|
||||
}
|
|
@ -5,9 +5,9 @@ const (
|
|||
)
|
||||
|
||||
fn test_type_ptr() {
|
||||
a := &Test{}
|
||||
b := []&Test
|
||||
c := &[]&Test
|
||||
_ := &Test{}
|
||||
_ := []&Test
|
||||
_ := &[]&Test
|
||||
}
|
||||
|
||||
struct Test {
|
||||
|
|
|
@ -14,27 +14,27 @@ import term
|
|||
|
||||
const (
|
||||
c_reserved = ['delete', 'exit', 'unix', 'error', 'calloc', 'malloc', 'free', 'panic', 'auto',
|
||||
'char'
|
||||
'default'
|
||||
'do'
|
||||
'double'
|
||||
'extern'
|
||||
'float'
|
||||
'inline'
|
||||
'int'
|
||||
'long'
|
||||
'register'
|
||||
'restrict'
|
||||
'short'
|
||||
'signed'
|
||||
'sizeof'
|
||||
'static'
|
||||
'switch'
|
||||
'typedef'
|
||||
'union'
|
||||
'unsigned'
|
||||
'void'
|
||||
'volatile'
|
||||
'char',
|
||||
'default',
|
||||
'do',
|
||||
'double',
|
||||
'extern',
|
||||
'float',
|
||||
'inline',
|
||||
'int',
|
||||
'long',
|
||||
'register',
|
||||
'restrict',
|
||||
'short',
|
||||
'signed',
|
||||
'sizeof',
|
||||
'static',
|
||||
'switch',
|
||||
'typedef',
|
||||
'union',
|
||||
'unsigned',
|
||||
'void',
|
||||
'volatile',
|
||||
'while'
|
||||
]
|
||||
)
|
||||
|
@ -1420,7 +1420,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
|||
g.expr_with_cast(node.right, node.right_type, info.elem_type)
|
||||
g.write(' })')
|
||||
}
|
||||
} else if (node.left_type == node.right_type) && node.left_type.is_float() && node.op in [.eq, .ne] {
|
||||
} else if (node.left_type == node.right_type) && node.left_type.is_float() && node.op in
|
||||
[.eq, .ne] {
|
||||
// floats should be compared with epsilon
|
||||
if node.left_type == table.f64_type_idx {
|
||||
if node.op == .eq {
|
||||
|
@ -1748,7 +1749,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||
}
|
||||
else {}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
if need_wrapper {
|
||||
g.write(', &($elem_type_str[]) { ')
|
||||
} else {
|
||||
|
@ -1810,7 +1811,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||
g.write(', ')
|
||||
g.expr(node.index)
|
||||
g.write('))')
|
||||
*/
|
||||
*/
|
||||
zero := g.type_default(info.value_type)
|
||||
g.write('(*($elem_type_str*)map_get3(')
|
||||
g.expr(node.left)
|
||||
|
@ -1916,7 +1917,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
|||
g.const_decl_simple_define(name, val)
|
||||
return
|
||||
}
|
||||
*/
|
||||
*/
|
||||
/*
|
||||
if table.is_number(field.typ) {
|
||||
g.const_decl_simple_define(name, val)
|
||||
|
@ -1926,7 +1927,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
|||
g.stringliterals.writeln('\t_const_$name = $val;')
|
||||
}
|
||||
} else {
|
||||
*/
|
||||
*/
|
||||
match field.expr {
|
||||
ast.CharLiteral {
|
||||
g.const_decl_simple_define(name, val)
|
||||
|
@ -1992,7 +1993,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
|||
} else {
|
||||
fields = struct_init.fields
|
||||
}
|
||||
*/
|
||||
*/
|
||||
// User set fields
|
||||
for _, field in struct_init.fields {
|
||||
field_name := c_name(field.name)
|
||||
|
@ -2378,8 +2379,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
|||
g.write('${str_fn_name}(')
|
||||
g.expr(expr)
|
||||
g.write(').str')
|
||||
}
|
||||
else if sym.kind == .enum_ {
|
||||
} else if sym.kind == .enum_ {
|
||||
is_var := match node.exprs[i] {
|
||||
ast.SelectorExpr { true }
|
||||
ast.Ident { true }
|
||||
|
@ -2718,7 +2718,7 @@ fn (g Gen) type_default(typ table.Type) string {
|
|||
}
|
||||
else {}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
match sym.name {
|
||||
'string' { return 'tos3("")' }
|
||||
'rune' { return '0' }
|
||||
|
@ -2747,7 +2747,7 @@ fn (g Gen) type_default(typ table.Type) string {
|
|||
'voidptr'{ '0'}
|
||||
else { '{0} '}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) write_tests_main() {
|
||||
|
@ -2948,7 +2948,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
|||
g.write('/* as */ *($styp*)')
|
||||
g.expr(node.expr)
|
||||
g.write('.obj')
|
||||
*/
|
||||
*/
|
||||
g.write('/* as */ *($styp*)__as_cast(')
|
||||
g.expr(node.expr)
|
||||
g.write('.obj, ')
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import (
|
||||
os
|
||||
v.pref
|
||||
v.builder
|
||||
term
|
||||
)
|
||||
import os
|
||||
import v.pref
|
||||
import v.builder
|
||||
import term
|
||||
|
||||
const (
|
||||
nr_tests = 4
|
||||
|
@ -35,8 +33,7 @@ fn test_c_files() {
|
|||
}
|
||||
if compare_texts(res, ctext, path) {
|
||||
println('${term_ok} ${i}')
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +53,6 @@ fn compare_texts(a, b, path string) bool {
|
|||
return false
|
||||
}
|
||||
*/
|
||||
|
||||
for i, line_a in lines_a {
|
||||
if i >= lines_b.len {
|
||||
println(line_a)
|
||||
|
|
|
@ -68,7 +68,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
|||
g.definitions.write(', ')
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
//
|
||||
g.fn_args(it.args, it.is_variadic)
|
||||
if it.no_body || (g.pref.is_cache && it.is_builtin) {
|
||||
|
@ -102,7 +102,6 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Profiling mode? Start counting at the beginning of the function (save current time).
|
||||
if g.pref.is_prof {
|
||||
if is_main {
|
||||
|
@ -112,17 +111,16 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
|||
}
|
||||
if it.name == 'time.sys_mono_now' {
|
||||
g.defer_profile_code = ''
|
||||
}else{
|
||||
} else {
|
||||
fn_profile_counter_name := 'vpc_${g.last_fn_c_name}'
|
||||
g.writeln('')
|
||||
g.writeln('\tdouble _PROF_FN_START = time__sys_mono_now(); ${fn_profile_counter_name}_calls++; // $it.name')
|
||||
g.writeln('')
|
||||
g.defer_profile_code = '\t${fn_profile_counter_name} += time__sys_mono_now() - _PROF_FN_START;'
|
||||
g.pcs_declarations.writeln('double ${fn_profile_counter_name} = 0.0; u64 ${fn_profile_counter_name}_calls = 0;')
|
||||
g.pcs[ g.last_fn_c_name ] = fn_profile_counter_name
|
||||
g.pcs[g.last_fn_c_name] = fn_profile_counter_name
|
||||
}
|
||||
}
|
||||
|
||||
g.stmts(it.stmts)
|
||||
// ////////////
|
||||
if g.autofree {
|
||||
|
@ -145,7 +143,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
|||
for pfn_name, pcounter_name in g.pcs {
|
||||
g.pcs_declarations.writeln('\tif (${pcounter_name}_calls) printf("%llu %f %f ${pfn_name} \\n", ${pcounter_name}_calls, $pcounter_name, $pcounter_name / ${pcounter_name}_calls );')
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
g.pcs_declarations.writeln('\tFILE * fp;')
|
||||
g.pcs_declarations.writeln('\tfp = fopen ("${g.pref.profile_file}", "w+");')
|
||||
for pfn_name, pcounter_name in g.pcs {
|
||||
|
@ -162,11 +160,11 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
|||
g.fn_decl = 0
|
||||
}
|
||||
|
||||
fn (mut g Gen) write_defer_stmts_when_needed(){
|
||||
fn (mut g Gen) write_defer_stmts_when_needed() {
|
||||
if g.defer_profile_code.len > 0 {
|
||||
g.writeln('')
|
||||
g.writeln('\t// defer_profile_code')
|
||||
g.writeln(g.defer_profile_code )
|
||||
g.writeln(g.defer_profile_code)
|
||||
g.writeln('')
|
||||
}
|
||||
if g.defer_stmts.len > 0 {
|
||||
|
@ -267,11 +265,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
}
|
||||
// TODO performance, detect `array` method differently
|
||||
if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many',
|
||||
'trim'
|
||||
'first'
|
||||
'last'
|
||||
'clone'
|
||||
'reverse'
|
||||
'trim',
|
||||
'first',
|
||||
'last',
|
||||
'clone',
|
||||
'reverse',
|
||||
'slice'
|
||||
] {
|
||||
// && rec_sym.name == 'array' {
|
||||
|
@ -298,8 +296,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
g.write('/*rec*/*')
|
||||
}
|
||||
g.expr(node.left)
|
||||
is_variadic := node.expected_arg_types.len > 0 &&
|
||||
node.expected_arg_types[node.expected_arg_types.len -1].flag_is(.variadic)
|
||||
is_variadic := node.expected_arg_types.len > 0 && node.expected_arg_types[node.expected_arg_types.len -
|
||||
1].flag_is(.variadic)
|
||||
if node.args.len > 0 || is_variadic {
|
||||
g.write(', ')
|
||||
}
|
||||
|
@ -313,7 +311,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
}
|
||||
println('')
|
||||
}
|
||||
*/
|
||||
*/
|
||||
// ///////
|
||||
g.call_args(node.args, node.expected_arg_types)
|
||||
g.write(')')
|
||||
|
@ -368,7 +366,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
g.writeln('; //memory')
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
if is_print && node.args[0].typ != table.string_type {
|
||||
typ := node.args[0].typ
|
||||
mut styp := g.typ(typ)
|
||||
|
@ -441,8 +439,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
}
|
||||
|
||||
fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||
is_variadic := expected_types.len > 0 &&
|
||||
expected_types[expected_types.len - 1].flag_is(.variadic)
|
||||
is_variadic := expected_types.len > 0 && expected_types[expected_types.len - 1].flag_is(.variadic)
|
||||
is_forwarding_varg := args.len > 0 && args[args.len - 1].typ.flag_is(.variadic)
|
||||
gen_vargs := is_variadic && !is_forwarding_varg
|
||||
mut arg_no := 0
|
||||
|
|
|
@ -1,48 +1,46 @@
|
|||
module js
|
||||
|
||||
import (
|
||||
strings
|
||||
v.ast
|
||||
)
|
||||
import strings
|
||||
import v.ast
|
||||
|
||||
struct JsDoc {
|
||||
gen &JsGen
|
||||
mut:
|
||||
mut:
|
||||
out strings.Builder
|
||||
empty_line bool
|
||||
}
|
||||
|
||||
fn new_jsdoc(gen &JsGen) &JsDoc {
|
||||
return &JsDoc {
|
||||
return &JsDoc{
|
||||
out: strings.new_builder(20)
|
||||
gen: gen
|
||||
}
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) gen_indent() {
|
||||
fn (mut d JsDoc) gen_indent() {
|
||||
if d.gen.indents[d.gen.namespace] > 0 && d.empty_line {
|
||||
d.out.write(tabs[d.gen.indents[d.gen.namespace]])
|
||||
}
|
||||
d.empty_line = false
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) write(s string) {
|
||||
fn (mut d JsDoc) write(s string) {
|
||||
d.gen_indent()
|
||||
d.out.write(s)
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) writeln(s string) {
|
||||
fn (mut d JsDoc) writeln(s string) {
|
||||
d.gen_indent()
|
||||
d.out.writeln(s)
|
||||
d.empty_line = true
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) reset() {
|
||||
fn (mut d JsDoc) reset() {
|
||||
d.out = strings.new_builder(20)
|
||||
d.empty_line = false
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) gen_typ(typ string, name string) string {
|
||||
fn (mut d JsDoc) gen_typ(typ, name string) string {
|
||||
d.reset()
|
||||
d.write('/**')
|
||||
d.write(' @type {$typ}')
|
||||
|
@ -53,13 +51,15 @@ fn (d mut JsDoc) gen_typ(typ string, name string) string {
|
|||
return d.out.str()
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) gen_ctor(fields []ast.StructField) string {
|
||||
fn (mut d JsDoc) gen_ctor(fields []ast.StructField) string {
|
||||
d.reset()
|
||||
d.writeln('/**')
|
||||
d.write('* @param {{')
|
||||
for i, field in fields {
|
||||
d.write('$field.name: ${d.gen.typ(field.typ)}')
|
||||
if i < fields.len-1 { d.write(', ') }
|
||||
if i < fields.len - 1 {
|
||||
d.write(', ')
|
||||
}
|
||||
}
|
||||
d.writeln('}} values - values for this class fields')
|
||||
d.writeln('* @constructor')
|
||||
|
@ -67,12 +67,14 @@ fn (d mut JsDoc) gen_ctor(fields []ast.StructField) string {
|
|||
return d.out.str()
|
||||
}
|
||||
|
||||
fn (d mut JsDoc) gen_fn(it ast.FnDecl) string {
|
||||
fn (mut d JsDoc) gen_fn(it ast.FnDecl) string {
|
||||
d.reset()
|
||||
type_name := d.gen.typ(it.return_type)
|
||||
d.writeln('/**')
|
||||
for i, arg in it.args {
|
||||
if it.is_method && i == 0 { continue }
|
||||
if it.is_method && i == 0 {
|
||||
continue
|
||||
}
|
||||
arg_type_name := d.gen.typ(arg.typ)
|
||||
is_varg := i == it.args.len - 1 && it.is_variadic
|
||||
if is_varg {
|
||||
|
|
|
@ -34,8 +34,9 @@ const (
|
|||
)
|
||||
|
||||
pub fn (mut g Gen) generate_elf_header() {
|
||||
g.buf << [byte(mag0), mag1
|
||||
mag2
|
||||
g.buf << [byte(mag0),
|
||||
mag1,
|
||||
mag2,
|
||||
mag3
|
||||
]
|
||||
g.buf << elfclass64 // file class
|
||||
|
@ -83,7 +84,7 @@ pub fn (mut g Gen) generate_elf_footer() {
|
|||
g.mov(.edi, 0) // ret value
|
||||
g.mov(.eax, 60)
|
||||
g.syscall()
|
||||
*/
|
||||
*/
|
||||
// Strings table
|
||||
// Loop thru all strings and set the right addresses
|
||||
for i, s in g.strings {
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module x64
|
||||
|
||||
/*
|
||||
This file is unused right now, since binaries without sections
|
||||
are generated.
|
||||
|
||||
But it will be necessary once we have dynamic linking.
|
||||
*/
|
||||
|
||||
|
||||
enum SectionType {
|
||||
null = 0
|
||||
progbits = 1
|
||||
|
@ -31,7 +30,7 @@ struct SectionConfig {
|
|||
entsize i64
|
||||
}
|
||||
|
||||
fn (g mut Gen) section_header(c SectionConfig) {
|
||||
fn (mut g Gen) section_header(c SectionConfig) {
|
||||
g.write32(g.sect_header_name_pos)
|
||||
g.sect_header_name_pos += c.name.len + 1
|
||||
g.write32(int(c.typ))
|
||||
|
@ -156,4 +155,3 @@ fn genobj() {
|
|||
})
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ pub fn (mut g Gen) push(reg Register) {
|
|||
.rbp { g.write8(0x55) }
|
||||
else {}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
g.println('push $reg')
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module parser
|
||||
|
||||
import (
|
||||
v.ast
|
||||
v.pref
|
||||
v.vmod
|
||||
)
|
||||
import v.ast
|
||||
import v.pref
|
||||
import v.vmod
|
||||
|
||||
const (
|
||||
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
|
||||
|
@ -23,14 +21,13 @@ fn (mut p Parser) hash() ast.HashStmt {
|
|||
mut flag := val[5..]
|
||||
// expand `@VROOT` to its absolute path
|
||||
if flag.contains('@VROOT') {
|
||||
vmod_file_location := vmod.mod_file_cacher.get( p.file_name_dir )
|
||||
vmod_file_location := vmod.mod_file_cacher.get(p.file_name_dir)
|
||||
if vmod_file_location.vmod_file.len == 0 {
|
||||
// There was no actual v.mod file found.
|
||||
p.error('To use @VROOT, you need' +
|
||||
' to have a "v.mod" file in ${p.file_name_dir},' +
|
||||
p.error('To use @VROOT, you need' + ' to have a "v.mod" file in ${p.file_name_dir},' +
|
||||
' or in one of its parent folders.')
|
||||
}
|
||||
flag = flag.replace('@VROOT', vmod_file_location.vmod_folder )
|
||||
flag = flag.replace('@VROOT', vmod_file_location.vmod_folder)
|
||||
}
|
||||
for deprecated in ['@VMOD', '@VMODULE', '@VPATH', '@VLIB_PATH'] {
|
||||
if flag.contains(deprecated) {
|
||||
|
@ -48,7 +45,7 @@ fn (mut p Parser) hash() ast.HashStmt {
|
|||
p.pref.cflags += val.after('darwin')
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
return ast.HashStmt{
|
||||
val: val
|
||||
|
@ -72,7 +69,8 @@ fn (mut p Parser) comp_if() ast.CompIf {
|
|||
// `$if os {` for a different target, skip everything inside
|
||||
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
|
||||
// on non-Windows systems)
|
||||
if !p.scanner.is_fmt && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c {
|
||||
if !p.scanner.is_fmt && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) &&
|
||||
!p.pref.output_cross_c {
|
||||
skip_os = true
|
||||
p.check(.lcbr)
|
||||
// p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os')
|
||||
|
|
|
@ -270,7 +270,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
|||
func.name = name
|
||||
idx := p.table.find_or_register_fn_type(func, true, false)
|
||||
typ := table.new_type(idx)
|
||||
//name := p.table.get_type_name(typ)
|
||||
// name := p.table.get_type_name(typ)
|
||||
return ast.AnonFn{
|
||||
decl: ast.FnDecl{
|
||||
name: name
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module parser
|
||||
|
||||
// return true if file being parsed imports `mod`
|
||||
pub fn (p &Parser) known_import(mod string) bool {
|
||||
return mod in p.imports
|
||||
|
|
|
@ -99,7 +99,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
|
|||
for p.tok.kind == .key_import {
|
||||
imports << p.import_stmt()
|
||||
}
|
||||
*/
|
||||
*/
|
||||
// TODO: import only mode
|
||||
for {
|
||||
// res := s.scan()
|
||||
|
@ -164,7 +164,7 @@ pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, g
|
|||
}
|
||||
time.sleep_ms(100)
|
||||
return q.parsed_ast_files
|
||||
*/
|
||||
*/
|
||||
// ///////////////
|
||||
mut files := []ast.File
|
||||
for path in paths {
|
||||
|
@ -187,7 +187,6 @@ pub fn (mut p Parser) read_first_token() {
|
|||
p.next()
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut p Parser) open_scope() {
|
||||
p.scope = &ast.Scope{
|
||||
parent: p.scope
|
||||
|
@ -198,7 +197,7 @@ pub fn (mut p Parser) open_scope() {
|
|||
pub fn (mut p Parser) close_scope() {
|
||||
if !p.pref.is_repl && !p.scanner.is_fmt {
|
||||
for v in p.scope.unused_vars() {
|
||||
if v.name.len > 0 && v.name[0]==`_` {
|
||||
if v.name.len > 0 && v.name[0] == `_` {
|
||||
continue
|
||||
}
|
||||
if p.pref.is_prod {
|
||||
|
@ -255,7 +254,7 @@ fn (mut p Parser) next() {
|
|||
p.comments << ast.Comment{text:p.tok.lit, line_nr:p.tok.line_nr}
|
||||
p.next()
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
fn (mut p Parser) check(expected token.Kind) {
|
||||
|
@ -638,9 +637,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
name_w_mod := p.prepend_mod(name)
|
||||
// type cast. TODO: finish
|
||||
// if name in table.builtin_type_names {
|
||||
if !known_var && (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) && !(name in ['C.stat',
|
||||
'C.sigaction'
|
||||
]) {
|
||||
if !known_var && (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) &&
|
||||
!(name in ['C.stat', 'C.sigaction']) {
|
||||
// TODO handle C.stat()
|
||||
mut to_typ := p.parse_type()
|
||||
if p.is_amp {
|
||||
|
@ -1080,7 +1078,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
|
|||
if !p.cgen.nogen {
|
||||
p.cgen.consts << g
|
||||
}
|
||||
*/
|
||||
*/
|
||||
glob := ast.GlobalDecl{
|
||||
name: name
|
||||
typ: typ
|
||||
|
@ -1099,7 +1097,6 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
|||
}
|
||||
p.check(.key_enum)
|
||||
end_pos := p.tok.position()
|
||||
|
||||
enum_name := p.check_name()
|
||||
if enum_name.len > 0 && !enum_name[0].is_capital() {
|
||||
verror('enum name `$enum_name` must begin with a capital letter')
|
||||
|
|
|
@ -162,7 +162,8 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
|||
}
|
||||
} else if p.tok.kind.is_infix() {
|
||||
// return early for deref assign `*x = 2` goes to prefix expr
|
||||
if p.tok.kind == .mul && p.tok.line_nr != p.prev_tok.line_nr && p.peek_tok2.kind == .assign {
|
||||
if p.tok.kind == .mul && p.tok.line_nr != p.prev_tok.line_nr && p.peek_tok2.kind ==
|
||||
.assign {
|
||||
return node
|
||||
}
|
||||
// continue on infix expr
|
||||
|
|
|
@ -71,7 +71,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
s := p.table.get_type_symbol(typ)
|
||||
println('XXXX' + s.str())
|
||||
}
|
||||
*/
|
||||
*/
|
||||
mut default_expr := ast.Expr{}
|
||||
mut has_default_expr := false
|
||||
if p.tok.kind == .assign {
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module pref
|
||||
|
||||
import (
|
||||
os
|
||||
term
|
||||
)
|
||||
import os
|
||||
import term
|
||||
|
||||
pub const (
|
||||
default_module_path = mpath()
|
||||
|
@ -22,7 +20,7 @@ pub fn new_preferences() Preferences {
|
|||
return p
|
||||
}
|
||||
|
||||
pub fn (p mut Preferences) fill_with_defaults() {
|
||||
pub fn (mut p Preferences) fill_with_defaults() {
|
||||
if p.vroot == '' {
|
||||
// Location of all vlib files
|
||||
p.vroot = os.dir(vexe_path())
|
||||
|
|
|
@ -171,16 +171,16 @@ pub const (
|
|||
|
||||
pub const (
|
||||
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
||||
u16_type_idx
|
||||
u32_type_idx
|
||||
u16_type_idx,
|
||||
u32_type_idx,
|
||||
u64_type_idx
|
||||
]
|
||||
float_type_idxs = [f32_type_idx, f64_type_idx]
|
||||
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
||||
u16_type_idx
|
||||
u32_type_idx
|
||||
u64_type_idx
|
||||
f32_type_idx
|
||||
u16_type_idx,
|
||||
u32_type_idx,
|
||||
u64_type_idx,
|
||||
f32_type_idx,
|
||||
f64_type_idx
|
||||
]
|
||||
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
||||
|
@ -213,10 +213,10 @@ pub const (
|
|||
|
||||
pub const (
|
||||
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64',
|
||||
'u16'
|
||||
'u32'
|
||||
'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed'
|
||||
'map', 'struct'
|
||||
'u16',
|
||||
'u32',
|
||||
'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed',
|
||||
'map', 'struct',
|
||||
'mapnode', 'size_t']
|
||||
)
|
||||
|
||||
|
@ -591,6 +591,6 @@ pub fn (table &Table) type_to_str(t Type) string {
|
|||
if res.starts_with(cur_mod +'.') {
|
||||
res = res[cur_mod.len+1.. ]
|
||||
}
|
||||
*/
|
||||
*/
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ fn (table &Table) has_cflag(flag cflag.CFlag) bool {
|
|||
|
||||
// parse the flags to (table.cflags) []CFlag
|
||||
// Note: clean up big time (joe-c)
|
||||
pub fn (table mut Table) parse_cflag(cflg, mod string, ctimedefines []string) ?bool {
|
||||
pub fn (mut table Table) parse_cflag(cflg, mod string, ctimedefines []string) ?bool {
|
||||
allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L']
|
||||
flag_orig := cflg.trim_space()
|
||||
mut flag := flag_orig
|
||||
|
|
|
@ -19,7 +19,7 @@ fn test_parse_valid_cflags() {
|
|||
make_flag('darwin', '-framework', 'Cocoa'),
|
||||
make_flag('windows', '-l', 'gdi32'),
|
||||
make_flag(no_os, '-l', 'mysqlclient'),
|
||||
make_flag(no_os, no_name, '-test'),
|
||||
make_flag(no_os, no_name, '-test')
|
||||
]
|
||||
parse_valid_flag(t, '-lmysqlclient')
|
||||
parse_valid_flag(t, '-test')
|
||||
|
|
Loading…
Reference in New Issue