fmt: lots of fixes

pull/4586/head
Enzo Baldisserri 2020-04-25 17:49:16 +02:00 committed by GitHub
parent 7c080c5d4a
commit fb54a2635c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 698 additions and 550 deletions

View File

@ -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

View File

@ -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'
}

View File

@ -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 {

View File

@ -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()

View File

@ -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',
// 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']
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'
]
// 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'
@ -172,8 +166,8 @@ fn (v mut Builder) cc() {
}
//
is_cc_clang := v.pref.ccompiler.contains('clang') || guessed_compiler == 'clang'
is_cc_tcc := v.pref.ccompiler.contains('tcc') || guessed_compiler == 'tcc'
is_cc_gcc := v.pref.ccompiler.contains('gcc') || guessed_compiler == 'gcc'
is_cc_tcc := v.pref.ccompiler.contains('tcc') || guessed_compiler == 'tcc'
is_cc_gcc := v.pref.ccompiler.contains('gcc') || guessed_compiler == 'gcc'
// is_cc_msvc := v.pref.ccompiler.contains('msvc') || guessed_compiler == 'msvc'
//
if is_cc_clang {
@ -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

View File

@ -36,4 +36,3 @@ fn (v &Builder) get_rest_of_module_cflags(c &cflag.CFlag) []cflag.CFlag {
}
return flags
}

View File

@ -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
@ -103,7 +107,7 @@ fn (v mut Builder) set_module_lookup_paths() {
// 3.2) search in ~/.vmodules/ (i.e. modules installed with vpm)
v.module_search_paths = []
if v.pref.is_test {
v.module_search_paths << os.base_dir(v.compiled_dir) // pdir of _test.v
v.module_search_paths << os.base_dir(v.compiled_dir) // pdir of _test.v
}
v.module_search_paths << v.compiled_dir
x := os.join_path(v.compiled_dir, 'modules')
@ -119,7 +123,7 @@ fn (v mut Builder) set_module_lookup_paths() {
}
pub fn (v Builder) get_builtin_files() []string {
if v.pref.build_mode == .build_module && v.pref.path == 'vlib/builtin' { // .contains('builtin/' + location {
if v.pref.build_mode == .build_module && v.pref.path == 'vlib/builtin' { // .contains('builtin/' + location {
// We are already building builtin.o, no need to import them again
if v.pref.is_verbose {
println('skipping builtin modules for builtin.o')

View File

@ -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
}

View File

@ -1,9 +1,7 @@
module builder
import (
os
time
)
import os
import time
fn (v &Builder) generate_hotcode_reloading_declarations() {
/*

View File

@ -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)
}
}

View File

@ -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
@ -35,7 +33,7 @@ mut:
// checked_ident string // to avoid infinit checker loops
var_decl_name string
returns bool
mod string // current module name
mod string // current module name
is_builtin_mod bool // are we in `builtin`?
}
@ -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) {
c.expected_type = table.none_type // TODO a hack to make `x := if ... work`
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,8 +1402,8 @@ 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 {
if ident.name == c.var_decl_name { // c.checked_ident {
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,10 +1684,10 @@ 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
mut is_range := false // TODO is_range := node.index is ast.RangeExpr
match node.index {
ast.RangeExpr {
is_range = true
@ -1754,10 +1733,10 @@ 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 { //
} else { //
c.table.find_type_idx(node.enum_name)
}
// println('checker: enum_val: $node.enum_name typeidx=$typ_idx')
@ -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) {
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 (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()

View File

@ -1,7 +1,5 @@
import (
v.table
v.doc
)
import v.table
import v.doc
fn test_vdoc() {
table := table.new_table()

View File

@ -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: ')
@ -66,22 +59,19 @@ fn (e mut Eval) stmt(node ast.Stmt) string {
return o.str()
}
// ast.StructDecl {
// println('s decl')
// println('s decl')
// }
ast.AssignStmt {
// TODO; replaced VarDecl
}
// ast.VarDecl {
// e.vars[it.name] = Var{
// value: e.expr(it.expr)
// }
// e.vars[it.name] = Var{
// value: e.expr(it.expr)
// }
// }
else {}
}
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,14 +88,10 @@ 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 {}
}
}
}
else {}
}

View File

@ -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 {
line_nr := expr.position().line_nr
if last_line_nr < line_nr {
if !inc_indent {
f.indent++
inc_indent = true
}
f.writeln('')
f.indent++
inc_indent = true
}
if i > 0 && it.exprs.len > 1 {
f.wrap_long_line()
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
f.writeln('')
} else if i < it.exprs.len - 1 {
f.write(', ')
if i == it.exprs.len - 1 {
if is_new_line {
f.writeln('')
}
} else {
f.write(',')
}
line_nr = pos.line_nr
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 {
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
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,25 +844,23 @@ 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 {
// `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
if it.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] {
if !(it.name in f.auto_imports) {
f.auto_imports << it.name
f.file.imports << ast.Import{
mod: it.name
alias: it.name
}
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
if it.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] {
if !(it.name in f.auto_imports) {
f.auto_imports << it.name
f.file.imports << ast.Import{
mod: it.name
alias: it.name
}
// for imp in f.file.imports {
// println(imp.mod)
// }
}
// for imp in f.file.imports {
// println(imp.mod)
// }
}
else {}
}
f.expr(node.left)
f.write('.' + node.name + '(')
@ -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 {

View File

@ -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

View File

@ -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()

View File

@ -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')
}

View File

@ -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')
}

View File

@ -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
}

View File

@ -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]
}

View File

@ -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]
}

View File

@ -1,7 +1,8 @@
fn test_as() {
a := sum_expr() as Bar
_ := a
}
fn test_cast() {
f := f32(0)
_ := f32(0)
}

View File

@ -1,7 +1,8 @@
fn test_as() {
a := sum_expr() as Bar
_ := a
}
fn test_cast() {
f := f32(0)
_ := f32(0)
}

View File

@ -0,0 +1,6 @@
fn concatenation_of_strings() {
_ := 'Simple' + 'Concat'
_ := 'Hello' + ' ' + 'World' + '!'
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" +
' ' + 'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
}

View File

@ -0,0 +1,7 @@
fn concatenation_of_strings() {
_ := 'Simple' + 'Concat'
_ := 'Hello'
+ ' ' +
'World' + '!'
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" + ' ' + 'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
}

View File

@ -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 }
}

View File

@ -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 }
}

View File

@ -1,7 +1,22 @@
const (
pi = 3.14
phi = 1.618
eulers = 2.7182
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 (

View File

@ -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
)

View File

@ -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')
}

View File

@ -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')
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -2,9 +2,21 @@
this is a very long comment
that is on multiple lines
and has some formatting in it
that should be
that should be
preserved.
*/
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 !
*/
}
}

View File

@ -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 ":\'("'
}

View File

@ -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 ":\'("'
}

View File

@ -5,9 +5,9 @@ const (
)
fn test_type_ptr() {
a := &Test{}
b := []&Test
c := &[]&Test
_ := &Test{}
_ := []&Test
_ := &[]&Test
}
struct Test {

View File

@ -14,28 +14,28 @@ 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'
'while'
'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, ')

View File

@ -1,13 +1,11 @@
import (
os
v.pref
v.builder
term
)
import os
import v.pref
import v.builder
import term
const (
nr_tests = 4
term_ok = term.ok_message('OK')
nr_tests = 4
term_ok = term.ok_message('OK')
term_fail = term.fail_message('FAIL')
)
@ -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)

View File

@ -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,9 +102,8 @@ 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 {
// Profiling mode? Start counting at the beginning of the function (save current time).
if g.pref.is_prof {
if is_main {
g.writeln('')
g.writeln('\tatexit(vprint_profile_stats);')
@ -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,12 +265,12 @@ 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'
'slice'
'trim',
'first',
'last',
'clone',
'reverse',
'slice'
] {
// && rec_sym.name == 'array' {
// && rec_sym.name == 'array' && receiver_name.starts_with('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

View File

@ -1,48 +1,46 @@
module js
import (
strings
v.ast
)
import strings
import v.ast
struct JsDoc {
gen &JsGen
mut:
out strings.Builder
gen &JsGen
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 {
@ -84,4 +86,4 @@ fn (d mut JsDoc) gen_fn(it ast.FnDecl) string {
d.writeln('* @return {$type_name}')
d.write('*/')
return d.out.str()
}
}

View File

@ -34,9 +34,10 @@ const (
)
pub fn (mut g Gen) generate_elf_header() {
g.buf << [byte(mag0), mag1
mag2
mag3
g.buf << [byte(mag0),
mag1,
mag2,
mag3
]
g.buf << elfclass64 // file class
g.buf << elfdata2lsb // data encoding
@ -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 {

View File

@ -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() {
})
*/
}

View File

@ -348,7 +348,7 @@ pub fn (mut g Gen) push(reg Register) {
.rbp { g.write8(0x55) }
else {}
}
*/
*/
g.println('push $reg')
}

View File

@ -14,7 +14,7 @@ fn (mut p Parser) assign_stmt() ast.Stmt {
}
idents := p.parse_assign_lhs()
op := p.tok.kind
p.next() // :=, =
p.next() // :=, =
pos := p.tok.position()
exprs := p.parse_assign_rhs()
is_decl := op == .decl_assign

View File

@ -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,12 +69,13 @@ 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')
mut stack := 1
for {
for {
if p.tok.kind == .key_return {
p.returns = true
}

View File

@ -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

View File

@ -95,7 +95,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
mut branches := []ast.MatchBranch
for {
branch_first_pos := p.tok.position()
comment := p.check_comment() // comment before {}
comment := p.check_comment() // comment before {}
mut exprs := []ast.Expr
p.open_scope()
// final else

View File

@ -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

View File

@ -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')

View File

@ -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

View File

@ -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 {

View File

@ -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())

View File

@ -171,17 +171,17 @@ 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
u64_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
f64_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]
string_type_idxs = [string_type_idx, ustring_type_idx]
@ -213,11 +213,11 @@ 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'
'mapnode', 'size_t']
'u16',
'u32',
'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed',
'map', 'struct',
'mapnode', 'size_t']
)
pub struct MultiReturn {
@ -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
}

View File

@ -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

View File

@ -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')