run vfmt on table.v

pull/3153/head
Alexander Medvednikov 2019-12-19 22:52:27 +03:00
parent 1679457f6b
commit ce86626ec2
5 changed files with 271 additions and 211 deletions

View File

@ -8,6 +8,7 @@ fn (p mut Parser) enum_decl(no_name bool) {
is_pub := p.tok == .key_pub is_pub := p.tok == .key_pub
if is_pub { if is_pub {
p.next() p.next()
p.fspace()
} }
p.check(.key_enum) p.check(.key_enum)
p.fspace() p.fspace()

View File

@ -46,6 +46,7 @@ fn (p mut Parser) match_statement(is_expr bool) string {
// allow braces is else // allow braces is else
got_brace := p.tok == .lcbr got_brace := p.tok == .lcbr
if got_brace { if got_brace {
p.fspace()
p.check(.lcbr) p.check(.lcbr)
} }
@ -73,7 +74,8 @@ fn (p mut Parser) match_statement(is_expr bool) string {
} }
if is_expr { if is_expr {
// statements are dissallowed (if match is expression) so user cant declare variables there and so on // statements are dissallowed (if match is expression) so
// user cant declare variables there and so on
p.gen(':(') p.gen(':(')
// allow braces is else // allow braces is else
@ -185,6 +187,7 @@ fn (p mut Parser) match_statement(is_expr bool) string {
} }
// braces are required for now // braces are required for now
p.fgen_nl()
p.check(.rcbr) p.check(.rcbr)
p.gen(')') p.gen(')')

View File

@ -419,14 +419,14 @@ fn (p mut Parser) parse(pass Pass) {
p.mod = p.check_name() p.mod = p.check_name()
} }
// //
p.fgenln('\n') p.fgen_nl()
p.cgen.nogen = false p.cgen.nogen = false
if p.pref.build_mode == .build_module && p.mod != p.v.mod { if p.pref.build_mode == .build_module && p.mod != p.v.mod {
// println('skipping $p.mod (v.mod = $p.v.mod)') // println('skipping $p.mod (v.mod = $p.v.mod)')
p.cgen.nogen = true p.cgen.nogen = true
// defer { p.cgen.nogen = false } // defer { p.cgen.nogen = false }
} }
p.fgenln('\n') p.fgen_nl()
p.builtin_mod = p.mod == 'builtin' p.builtin_mod = p.mod == 'builtin'
p.can_chash = p.mod in ['ui', 'darwin', 'clipboard', 'webview'] // TODO tmp remove p.can_chash = p.mod in ['ui', 'darwin', 'clipboard', 'webview'] // TODO tmp remove
// Import pass - the first and the smallest pass that only analyzes imports // Import pass - the first and the smallest pass that only analyzes imports
@ -466,7 +466,6 @@ fn (p mut Parser) parse(pass Pass) {
} }
} }
.key_pub { .key_pub {
p.fspace()
next := p.peek() next := p.peek()
match next { match next {
.key_fn { .key_fn {
@ -522,6 +521,7 @@ fn (p mut Parser) parse(pass Pass) {
p.next() p.next()
p.fspace() p.fspace()
name := p.check_name() name := p.check_name()
p.fspace()
typ := p.get_type() typ := p.get_type()
p.register_global(name, typ) p.register_global(name, typ)
// p.genln(p.table.cgen_name_type_pair(name, typ)) // p.genln(p.table.cgen_name_type_pair(name, typ))
@ -665,6 +665,7 @@ fn (p mut Parser) const_decl() {
is_pub := p.tok == .key_pub is_pub := p.tok == .key_pub
if is_pub { if is_pub {
p.next() p.next()
p.fspace()
} }
p.inside_const = true p.inside_const = true
p.check(.key_const) p.check(.key_const)
@ -770,9 +771,12 @@ fn (p mut Parser) type_decl() {
is_pub := p.tok == .key_pub is_pub := p.tok == .key_pub
if is_pub { if is_pub {
p.next() p.next()
p.fspace()
} }
p.check(.key_type) p.check(.key_type)
p.fspace()
name := p.check_name() name := p.check_name()
p.fspace()
// V used to have 'type Foo struct', many Go users might use this syntax // V used to have 'type Foo struct', many Go users might use this syntax
if p.tok == .key_struct { if p.tok == .key_struct {
p.error('use `struct $name {` instead of `type $name struct {`') p.error('use `struct $name {` instead of `type $name struct {`')
@ -867,7 +871,7 @@ fn (p &Parser) strtok() string {
return '`$p.lit`' return '`$p.lit`'
} }
if p.tok == .str { if p.tok == .str {
if p.lit.contains("'") { if p.lit.contains("'") && !p.lit.contains('"') {
return '"$p.lit"' return '"$p.lit"'
} }
else { else {
@ -2989,3 +2993,4 @@ fn (p &Parser) is_expr_fn_call(start_tok_idx int) (bool,string) {
fn todo_remove() { fn todo_remove() {
x64.new_gen('f') x64.new_gen('f')
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module compiler module compiler
import strings import strings
@ -153,50 +152,19 @@ pub fn (t Type) str() string {
} }
*/ */
const ( const (
c_reserved = [ c_reserved = ['delete', 'exit', 'unix',
'delete',
'exit',
'unix',
// 'print', // 'print',
// 'ok', // 'ok',
'error', 'error', 'malloc', 'calloc', 'free', 'panic',
'malloc',
'calloc',
'free',
'panic',
// Full list of C reserved words, from: https://en.cppreference.com/w/c/keyword // Full list of C reserved words, from: https://en.cppreference.com/w/c/keyword
'auto', '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',
]
) )
// This is used for debugging only // This is used for debugging only
pub fn (f Fn) str() string { pub fn (f Fn) str() string {
t := Table{} t := Table{
}
str_args := f.str_args(t) str_args := f.str_args(t)
return '${f.name}($str_args) $f.typ' return '${f.name}($str_args) $f.typ'
} }
@ -241,10 +209,12 @@ fn (t mut Table) register_enum_val(typ, val string) {
} }
*/ */
fn new_table(obfuscate bool) &Table { fn new_table(obfuscate bool) &Table {
mut t := &Table{ mut t := &Table{
obfuscate: obfuscate obfuscate: obfuscate
// enum_vals: map[string][]string // enum_vals: map[string][]string
} }
t.register_builtin('int') t.register_builtin('int')
t.register_builtin('size_t') t.register_builtin('size_t')
@ -367,7 +337,8 @@ fn (table &Table) known_type_fast(t &Type) bool {
fn (t &Table) find_fn(name string) ?Fn { fn (t &Table) find_fn(name string) ?Fn {
f := t.fns[name] f := t.fns[name]
if f.name.str != 0 { // TODO if f.name.str != 0 {
// TODO
return f return f
} }
return none return none
@ -375,7 +346,8 @@ fn (t &Table) find_fn(name string) ?Fn {
fn (t &Table) find_fn_is_script(name string, is_script bool) ?Fn { fn (t &Table) find_fn_is_script(name string, is_script bool) ?Fn {
mut f := t.fns[name] mut f := t.fns[name]
if f.name.str != 0 { // TODO if f.name.str != 0 {
// TODO
return f return f
} }
// V script? Try os module. // V script? Try os module.
@ -390,12 +362,16 @@ fn (t &Table) find_fn_is_script(name string, is_script bool) ?Fn {
} }
fn (t &Table) known_fn(name string) bool { fn (t &Table) known_fn(name string) bool {
_ = t.find_fn(name) or { return false } _ = t.find_fn(name) or {
return false
}
return true return true
} }
fn (t &Table) known_const(name string) bool { fn (t &Table) known_const(name string) bool {
_ = t.find_const(name) or { return false } _ = t.find_const(name) or {
return false
}
return true return true
} }
@ -406,7 +382,10 @@ fn (t mut Table) register_builtin(typ string) {
if typ in t.typesmap { if typ in t.typesmap {
return return
} }
t.typesmap[typ] = Type{name:typ, is_public:true} t.typesmap[typ] = Type{
name: typ
is_public: true
}
} }
fn (p mut Parser) register_type_with_parent(strtyp, parent string) { fn (p mut Parser) register_type_with_parent(strtyp, parent string) {
@ -428,6 +407,7 @@ fn (t mut Table) register_type_with_parent(typ, parent string) {
parent: parent parent: parent
is_public: true is_public: true
// mod: mod // mod: mod
} }
} }
@ -457,6 +437,7 @@ fn (table mut Table) add_field(type_name, field_name, field_type string, is_mut
is_mut: is_mut is_mut: is_mut
attr: attr attr: attr
parent_fn: type_name // Name of the parent type parent_fn: type_name // Name of the parent type
access_mod: access_mod access_mod: access_mod
} }
table.typesmap[type_name] = t table.typesmap[type_name] = t
@ -472,7 +453,9 @@ fn (table mut Table) add_default_val(idx int, type_name, val_expr string) {
} }
fn (t &Type) has_field(name string) bool { fn (t &Type) has_field(name string) bool {
_ = t.find_field(name) or { return false } _ = t.find_field(name) or {
return false
}
return true return true
} }
@ -490,7 +473,9 @@ fn (t &Type) find_field(name string) ?Var {
} }
fn (table &Table) type_has_field(typ &Type, name string) bool { fn (table &Table) type_has_field(typ &Type, name string) bool {
_ = table.find_field(typ, name) or { return false } _ = table.find_field(typ, name) or {
return false
}
return true return true
} }
@ -529,12 +514,16 @@ fn (p mut Parser) add_method(type_name string, f Fn) {
} }
fn (t &Type) has_method(name string) bool { fn (t &Type) has_method(name string) bool {
_ = t.find_method(name) or { return false } _ = t.find_method(name) or {
return false
}
return true return true
} }
fn (table &Table) type_has_method(typ &Type, name string) bool { fn (table &Table) type_has_method(typ &Type, name string) bool {
_ = table.find_method(typ, name) or { return false } _ = table.find_method(typ, name) or {
return false
}
return true return true
} }
@ -592,7 +581,8 @@ fn (t &Table) find_type(name_ string) Type {
} }
if !(name in t.typesmap) { if !(name in t.typesmap) {
// println('ret Type') // println('ret Type')
return Type{} return Type{
}
} }
return t.typesmap[name] return t.typesmap[name]
} }
@ -607,7 +597,6 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
if got == expected { if got == expected {
return true return true
} }
// generic return type // generic return type
if expected == '_ANYTYPE_' { if expected == '_ANYTYPE_' {
p.cur_fn.typ = got p.cur_fn.typ = got
@ -647,7 +636,8 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
return true return true
} }
// Todo void* allows everything right now // Todo void* allows everything right now
if got=='void*' || expected=='void*' {// || got == 'cvoid' || expected == 'cvoid' { if got == 'void*' || expected == 'void*' {
// || got == 'cvoid' || expected == 'cvoid' {
return true return true
} }
// TODO only allow numeric consts to be assigned to bytes, and // TODO only allow numeric consts to be assigned to bytes, and
@ -699,8 +689,7 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
// return true // return true
// } // }
// TODO fn hack // TODO fn hack
if got.starts_with('fn ') && (expected.ends_with('fn') || if got.starts_with('fn ') && (expected.ends_with('fn') || expected.ends_with('Fn')) {
expected.ends_with('Fn')) {
return true return true
} }
// Allow pointer arithmetic // Allow pointer arithmetic
@ -714,15 +703,14 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
if is_integer_type(got) && is_number_type(expected) && p.is_const_literal { if is_integer_type(got) && is_number_type(expected) && p.is_const_literal {
return true return true
} }
if expected == 'integer' { if expected == 'integer' {
if is_integer_type(got) { if is_integer_type(got) {
return true return true
} else { }
else {
p.error('expected type `$expected`, but got `$got`') p.error('expected type `$expected`, but got `$got`')
} }
} }
expected = expected.replace('*', '') expected = expected.replace('*', '')
got = got.replace('*', '').replace('ptr', '') got = got.replace('*', '').replace('ptr', '')
if got != expected { if got != expected {
@ -752,7 +740,9 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
// throw by default // throw by default
fn (p mut Parser) check_types(got, expected string) bool { fn (p mut Parser) check_types(got, expected string) bool {
if p.first_pass() { return true } if p.first_pass() {
return true
}
return p.check_types2(got, expected, true) return p.check_types2(got, expected, true)
} }
@ -772,8 +762,7 @@ fn (p mut Parser) satisfies_interface(interface_name, _typ string, throw bool) b
for method in int_typ.methods { for method in int_typ.methods {
if !typ.has_method(method.name) { if !typ.has_method(method.name) {
// if throw { // if throw {
p.error('type `$_typ` doesn\'t satisfy interface ' + p.error("type `$_typ` doesn\'t satisfy interface " + '`$interface_name` (method `$method.name` is not implemented)')
'`$interface_name` (method `$method.name` is not implemented)')
// } // }
return false return false
} }
@ -781,7 +770,6 @@ fn (p mut Parser) satisfies_interface(interface_name, _typ string, throw bool) b
return true return true
} }
fn (table &Table) is_interface(name string) bool { fn (table &Table) is_interface(name string) bool {
if !(name in table.typesmap) { if !(name in table.typesmap) {
return false return false
@ -850,21 +838,28 @@ fn (table &Table) cgen_name_type_pair(name, typ string) string {
fn is_valid_int_const(val, typ string) bool { fn is_valid_int_const(val, typ string) bool {
x := val.int() x := val.int()
return match typ { return match typ {
'byte' { 0 <= x && x <= 255 } 'byte'{
'u16' { 0 <= x && x <= 65535 } 0 <= x && x <= 255
}
'u16'{
0 <= x && x <= 65535
}
// case 'u32': return 0 <= x && x <= math.MaxU32 // case 'u32': return 0 <= x && x <= math.MaxU32
// case 'u64': return 0 <= x && x <= math.MaxU64 // case 'u64': return 0 <= x && x <= math.MaxU64
// //////////// // ////////////
'i8' { -128 <= x && x <= 127 } 'i8'{
-128 <= x && x <= 127
}
/* /*
case 'i16': return math.min_i16 <= x && x <= math.max_i16 case 'i16': return math.min_i16 <= x && x <= math.max_i16
case 'int': return math.min_i32 <= x && x <= math.max_i32 case 'int': return math.min_i32 <= x && x <= math.max_i32
*/ */
// case 'i64': // case 'i64':
// x64 := val.i64() // x64 := val.i64()
// return i64(-(1<<63)) <= x64 && x64 <= i64((1<<63)-1) // return i64(-(1<<63)) <= x64 && x64 <= i64((1<<63)-1)
else { true } else {
} true}}
} }
fn (p mut Parser) typ_to_fmt(typ string, level int) string { fn (p mut Parser) typ_to_fmt(typ string, level int) string {
@ -873,24 +868,41 @@ fn (p mut Parser) typ_to_fmt(typ string, level int) string {
return '%d' return '%d'
} }
match typ { match typ {
'string' { return '%.*s'} 'string' {
return '%.*s'
}
// case 'bool': return '%.*s' // case 'bool': return '%.*s'
'ustring' { return '%.*s'} 'ustring' {
'byte', 'bool', 'int', 'char', 'byte', 'i16', 'i8' { return '%d'} return '%.*s'
'u16', 'u32' { return '%u'} }
'f64', 'f32' { return '%f'} 'byte','bool','int','char','byte','i16','i8' {
'i64' { return '%lld'} return '%d'
'u64' { return '%llu'} }
'byte*', 'byteptr' { return '%s'} 'u16','u32' {
return '%u'
}
'f64','f32' {
return '%f'
}
'i64' {
return '%lld'
}
'u64' {
return '%llu'
}
'byte*','byteptr' {
return '%s'
}
// case 'array_string': return '%s' // case 'array_string': return '%s'
// case 'array_int': return '%s' // case 'array_int': return '%s'
'void' { p.error('cannot interpolate this value')} 'void' {
p.error('cannot interpolate this value')
}
else { else {
if typ.ends_with('*') { if typ.ends_with('*') {
return '%p' return '%p'
} }
} }}
}
if t.parent != '' && level == 0 { if t.parent != '' && level == 0 {
return p.typ_to_fmt(t.parent, level + 1) return p.typ_to_fmt(t.parent, level + 1)
} }
@ -907,7 +919,7 @@ fn is_compile_time_const(s_ string) bool {
if s == '' { if s == '' {
return false return false
} }
if s.contains('\'') { if s.contains("\'") {
return true return true
} }
for c in s { for c in s {
@ -933,7 +945,9 @@ fn (t &Type) contains_field_type(typ string) bool {
// check for a function / variable / module typo in `name` // check for a function / variable / module typo in `name`
fn (p &Parser) identify_typo(name string) string { fn (p &Parser) identify_typo(name string) string {
// dont check if so short // dont check if so short
if name.len < 2 { return '' } if name.len < 2 {
return ''
}
name_dotted := mod_gen_name_rev(name.replace('__', '.')) name_dotted := mod_gen_name_rev(name.replace('__', '.'))
min_match := 0.50 // for dice coefficient between 0.0 - 1.0 min_match := 0.50 // for dice coefficient between 0.0 - 1.0
mut output := '' mut output := ''
@ -967,13 +981,21 @@ fn (p &Parser) identify_typo(name string) string {
// compare just name part, some items are mod prefied // compare just name part, some items are mod prefied
fn typo_compare_name_mod(a, b, b_mod string) f32 { fn typo_compare_name_mod(a, b, b_mod string) f32 {
if a.len - b.len > 2 || b.len - a.len > 2 { return 0 } if a.len - b.len > 2 || b.len - a.len > 2 {
auidx := a.index('__') or { return 0 } // TODO or {-1} once cgen lines bug is fixed //-1 } return 0
buidx := b.index('__') or { return 0 } //-1 } }
auidx := a.index('__') or {
return 0
} // TODO or {-1} once cgen lines bug is fixed //-1 }
buidx := b.index('__') or {
return 0
} // -1 }
a_mod := if auidx != -1 { mod_gen_name_rev(a[..auidx]) } else { '' } a_mod := if auidx != -1 { mod_gen_name_rev(a[..auidx]) } else { '' }
a_name := if auidx != -1 { a[auidx + 2..] } else { a } a_name := if auidx != -1 { a[auidx + 2..] } else { a }
b_name := if buidx != -1 { b[buidx + 2..] } else { b } b_name := if buidx != -1 { b[buidx + 2..] } else { b }
if a_mod.len > 0 && b_mod.len > 0 && a_mod != b_mod { return 0 } if a_mod.len > 0 && b_mod.len > 0 && a_mod != b_mod {
return 0
}
return strings.dice_coefficient(a_name, b_name) return strings.dice_coefficient(a_name, b_name)
} }
@ -982,7 +1004,9 @@ fn (table &Table) find_misspelled_fn(name string, p &Parser, min_match f32) stri
mut closest := f32(0) mut closest := f32(0)
mut closest_fn := '' mut closest_fn := ''
for _, f in table.fns { for _, f in table.fns {
if f.name.contains('__') && !p.is_mod_in_scope(f.mod) { continue } if f.name.contains('__') && !p.is_mod_in_scope(f.mod) {
continue
}
c := typo_compare_name_mod(name, f.name, f.mod) c := typo_compare_name_mod(name, f.name, f.mod)
if c > closest { if c > closest {
closest = c closest = c
@ -1012,7 +1036,9 @@ fn (table &Table) find_misspelled_const(name string, p &Parser, min_match f32) s
mut closest := f32(0) mut closest := f32(0)
mut closest_const := '' mut closest_const := ''
for cnst in table.consts { for cnst in table.consts {
if cnst.name.contains('__') && !p.is_mod_in_scope(cnst.mod) { continue } if cnst.name.contains('__') && !p.is_mod_in_scope(cnst.mod) {
continue
}
c := typo_compare_name_mod(name, cnst.name, cnst.mod) c := typo_compare_name_mod(name, cnst.name, cnst.mod)
if c > closest { if c > closest {
closest = c closest = c
@ -1028,7 +1054,9 @@ fn (table &Table) find_misspelled_type(name string, p &Parser, min_match f32) (s
mut closest_type := '' mut closest_type := ''
mut type_cat := '' mut type_cat := ''
for _, typ in table.typesmap { for _, typ in table.typesmap {
if typ.name.contains('__') && !p.is_mod_in_scope(typ.mod) { continue } if typ.name.contains('__') && !p.is_mod_in_scope(typ.mod) {
continue
}
c := typo_compare_name_mod(name, typ.name, typ.mod) c := typo_compare_name_mod(name, typ.name, typ.mod)
if c > closest { if c > closest {
closest = c closest = c
@ -1044,18 +1072,41 @@ fn (table &Table) find_misspelled_type(name string, p &Parser, min_match f32) (s
fn type_cat_str(tc TypeCategory) string { fn type_cat_str(tc TypeCategory) string {
tc_str := match tc { tc_str := match tc {
.builtin { 'builtin' } .builtin{
.struct_ { 'struct' } 'builtin'
.func { 'function' }
.interface_ { 'interface' }
.enum_ { 'enum' }
.union_ { 'union' }
.c_struct { 'C struct' }
.c_typedef { 'C typedef' }
.objc_interface { 'obj C interface' }
.array { 'array' }
.alias { 'type alias' }
else { 'unknown' }
} }
.struct_{
'struct'
}
.func{
'function'
}
.interface_{
'interface'
}
.enum_{
'enum'
}
.union_{
'union'
}
.c_struct{
'C struct'
}
.c_typedef{
'C typedef'
}
.objc_interface{
'obj C interface'
}
.array{
'array'
}
.alias{
'type alias'
}
else {
'unknown'}}
return tc_str return tc_str
} }

View File

@ -250,11 +250,11 @@ fn (p &Parser) gen_fmt() {
if s == '' { if s == '' {
return return
} }
if !p.file_path.contains('fn.v') {return} if !p.file_path.contains('table.v') {return}
path := os.tmpdir() + '/' + p.file_name path := os.tmpdir() + '/' + p.file_name
println('generating ${path}') println('generating ${path}')
mut out := os.create(path) or { mut out := os.create(path) or {
verror('failed to create fmt.v') verror('failed to create os_nix.v')
return return
} }
println('replacing ${p.file_path}...\n') println('replacing ${p.file_path}...\n')