1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

fmt: remove trailing spaces

This commit is contained in:
Alexander Medvednikov 2019-08-17 22:19:37 +03:00
parent 8a1324c141
commit fe2d2bd2a3
9 changed files with 1049 additions and 1049 deletions

View File

@ -4,7 +4,7 @@
module main
import strings
import strings
const (
MaxLocalVars = 50
@ -30,7 +30,7 @@ mut:
returns_error bool
is_decl bool // type myfn fn(int, int)
defer_text []string
//gen_types []string
//gen_types []string
}
fn (f &Fn) find_var(name string) Var {
@ -114,12 +114,12 @@ fn new_fn(mod string, is_public bool) *Fn {
// Function signatures are added to the top of the .c file in the first run.
fn (p mut Parser) fn_decl() {
p.fgen('fn ')
//defer { p.fgenln('\n') }
is_pub := p.tok == .key_pub
is_live := p.attr == 'live' && !p.pref.is_so && p.pref.is_live
if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so {
println('INFO: run `v -live program.v` if you want to use [live] functions')
}
//defer { p.fgenln('\n') }
is_pub := p.tok == .key_pub
is_live := p.attr == 'live' && !p.pref.is_so && p.pref.is_live
if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so {
println('INFO: run `v -live program.v` if you want to use [live] functions')
}
if is_pub {
p.next()
}
@ -136,7 +136,7 @@ fn (p mut Parser) fn_decl() {
is_mut := p.tok == .key_mut
is_amp := p.tok == .amp
if is_mut || is_amp {
p.check_space(p.tok)
p.check_space(p.tok)
}
receiver_typ = p.get_type()
T := p.table.find_type(receiver_typ)
@ -159,7 +159,7 @@ fn (p mut Parser) fn_decl() {
receiver_typ += '*'
}
p.check(.rpar)
p.fspace()
p.fspace()
receiver := Var {
name: receiver_name
is_arg: true
@ -180,7 +180,7 @@ fn (p mut Parser) fn_decl() {
f.name = p.check_name()
}
// C function header def? (fn C.NSMakeRect(int,int,int,int))
is_c := f.name == 'C' && p.tok == .dot
is_c := f.name == 'C' && p.tok == .dot
// Just fn signature? only builtin.v + default build mode
// is_sig := p.builtin_mod && p.pref.build_mode == default_mode
// is_sig := p.pref.build_mode == default_mode && (p.builtin_mod || p.file.contains(LANG_TMP))
@ -228,12 +228,12 @@ fn (p mut Parser) fn_decl() {
p.error('only `T` is allowed as a generic type for now')
}
p.check(.gt)
if p.first_pass() {
p.table.register_generic_fn(f.name)
} else {
//gen_types := p.table.fn_gen_types(f.name)
//println(gen_types)
}
if p.first_pass() {
p.table.register_generic_fn(f.name)
} else {
//gen_types := p.table.fn_gen_types(f.name)
//println(gen_types)
}
}
// Args (...)
p.fn_args(mut f)
@ -252,7 +252,7 @@ fn (p mut Parser) fn_decl() {
typ = p.get_type()
}
// Translated C code can have empty functions (just definitions)
is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr
is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr
if is_fn_header {
f.is_decl = true
}
@ -279,12 +279,12 @@ fn (p mut Parser) fn_decl() {
dll_export_linkage := if p.os == .msvc && p.attr == 'live' && p.pref.is_so {
'__declspec(dllexport) '
} else {
''
}
if !p.is_vweb {
''
}
if !p.is_vweb {
p.cur_fn = f
}
// Generate `User_register()` instead of `register()`
}
// Generate `User_register()` instead of `register()`
// Internally it's still stored as "register" in type User
mut fn_name_cgen := p.table.cgen_name(f)
// Start generation of the function body
@ -293,27 +293,27 @@ fn (p mut Parser) fn_decl() {
if p.pref.obfuscate {
p.genln('; // $f.name')
}
// Generate this function's body for all generic types
if is_generic {
gen_types := p.table.fn_gen_types(f.name)
// Generate this function's body for all generic types
if is_generic {
gen_types := p.table.fn_gen_types(f.name)
// Remember current scanner position, go back here for each type
// TODO remove this once tokens are cached in `new_parser()`
cur_pos := p.scanner.pos
cur_tok := p.tok
cur_lit := p.lit
// TODO remove this once tokens are cached in `new_parser()`
cur_pos := p.scanner.pos
cur_tok := p.tok
cur_lit := p.lit
for gen_type in gen_types {
p.genln('$dll_export_linkage$typ ${fn_name_cgen}_$gen_type($str_args) {')
p.genln('// T start $p.pass ${p.strtok()}')
p.cur_gen_type = gen_type // TODO support more than T
p.genln('$dll_export_linkage$typ ${fn_name_cgen}_$gen_type($str_args) {')
p.genln('// T start $p.pass ${p.strtok()}')
p.cur_gen_type = gen_type // TODO support more than T
p.statements()
p.scanner.pos = cur_pos
p.tok = cur_tok
p.lit = cur_lit
}
}
else {
p.scanner.pos = cur_pos
p.tok = cur_tok
p.lit = cur_lit
}
}
else {
p.genln('$dll_export_linkage$typ $fn_name_cgen($str_args) {')
}
}
}
if is_fn_header {
p.genln('$typ $fn_name_cgen($str_args);')
@ -329,11 +329,11 @@ fn (p mut Parser) fn_decl() {
// struct declaration later will modify it instead of creating a new one.
if p.first_pass() && receiver_t.name == '' {
// println('fn decl !!!!!!! REG PH $receiver_typ')
p.table.register_type2(Type {
p.table.register_type2(Type {
name: receiver_typ.replace('*', '')
mod: p.mod
is_placeholder: true
})
})
}
// f.idx = p.table.fn_cnt
receiver_t.add_method(f)
@ -343,8 +343,8 @@ fn (p mut Parser) fn_decl() {
p.table.register_fn(f)
}
if is_sig || p.first_pass() || is_live || is_fn_header || skip_main_in_test {
// First pass? Skip the body for now
// Look for generic calls.
// First pass? Skip the body for now
// Look for generic calls.
if !is_sig && !is_fn_header {
mut opened_scopes := 0
mut closed_scopes := 0
@ -357,23 +357,23 @@ fn (p mut Parser) fn_decl() {
closed_scopes++
}
p.next()
// find `foo<Bar>()` in function bodies and register generic types
// TODO remove this once tokens are cached
// find `foo<Bar>()` in function bodies and register generic types
// TODO remove this once tokens are cached
if p.tok == .gt && p.prev_tok == .name && p.prev_tok2 == .lt &&
p.scanner.text[p.scanner.pos-1] != `T` {
temp_scanner_pos = p.scanner.pos
p.scanner.pos -= 3
for p.scanner.pos > 0 && (is_name_char(p.scanner.text[p.scanner.pos]) ||
p.scanner.pos -= 3
for p.scanner.pos > 0 && (is_name_char(p.scanner.text[p.scanner.pos]) ||
p.scanner.text[p.scanner.pos] == `.` ||
p.scanner.text[p.scanner.pos] == `<` ) {
p.scanner.pos--
}
p.scanner.pos--
p.next()
// Run the function in the firt pass to register the generic type
p.name_expr()
p.scanner.text[p.scanner.pos] == `<` ) {
p.scanner.pos--
}
p.scanner.pos--
p.next()
// Run the function in the firt pass to register the generic type
p.name_expr()
p.scanner.pos = temp_scanner_pos
}
}
if p.tok.is_decl() && !(p.prev_tok == .dot && p.tok == .key_type) {
break
}
@ -382,16 +382,16 @@ fn (p mut Parser) fn_decl() {
if p.tok == .lsbr {
break
}
}
}
}
}
// Live code reloading? Load all fns from .so
if is_live && p.first_pass() && p.mod == 'main' {
//println('ADDING SO FN $fn_name_cgen')
//println('ADDING SO FN $fn_name_cgen')
p.cgen.so_fns << fn_name_cgen
fn_name_cgen = '(* $fn_name_cgen )'
}
// Function definition that goes to the top of the C file.
// Function definition that goes to the top of the C file.
mut fn_decl := '$dll_export_linkage$typ $fn_name_cgen($str_args)'
if p.pref.obfuscate {
fn_decl += '; // $f.name'
@ -422,15 +422,15 @@ fn (p mut Parser) fn_decl() {
}
// We are in live code reload mode, call the .so loader in bg
if p.pref.is_live {
file_base := p.file_path.replace('.v', '')
file_base := p.file_path.replace('.v', '')
if p.os != .windows && p.os != .msvc {
so_name := file_base + '.so'
p.genln('
load_so("$so_name");
p.genln('
load_so("$so_name");
pthread_t _thread_so;
pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
} else {
so_name := file_base + if p.os == .msvc {'.dll'} else {'.so'}
so_name := file_base + if p.os == .msvc {'.dll'} else {'.so'}
p.genln('
live_fn_mutex = CreateMutexA(0, 0, 0);
load_so("$so_name");
@ -454,20 +454,20 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0);
cgen_name := p.table.cgen_name(f)
f.defer_text[f.scope_level] = ' ${cgen_name}_time += time__ticks() - _PROF_START;'
}
if is_generic {
// Don't need to generate body for the actual generic definition
p.cgen.nogen = true
}
if is_generic {
// Don't need to generate body for the actual generic definition
p.cgen.nogen = true
}
p.statements_no_rcbr()
p.cgen.nogen = false
p.cgen.nogen = false
// Print counting result after all statements in main
if p.pref.is_prof && f.name == 'main' {
p.genln(p.print_prof_counters())
}
// Counting or not, always need to add defer before the end
if !p.is_vweb {
if !p.is_vweb {
p.genln(f.defer_text[f.scope_level])
}
}
if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' {
p.error('$f.name must return "$typ"')
}
@ -485,16 +485,16 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0);
// Make sure all vars in this function are used (only in main for now)
// if p.builtin_mod || p.mod == 'os' ||p.mod=='http'{
if p.mod != 'main' {
if !is_generic {
if !is_generic {
p.genln('}')
}
}
return
}
p.check_unused_variables()
p.cur_fn = EmptyFn
if !is_generic {
if !is_generic {
p.genln('}')
}
}
}
fn (p mut Parser) check_unused_variables() {
@ -508,7 +508,7 @@ fn (p mut Parser) check_unused_variables() {
}
if !var.is_changed && var.is_mut && !p.pref.is_repl && !var.is_arg && !p.pref.translated && var.name != '_' {
p.scanner.line_nr = var.line_nr - 1
p.error('`$var.name` is declared as mutable, but it was never changed')
p.error('`$var.name` is declared as mutable, but it was never changed')
}
}
}
@ -524,7 +524,7 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
// Normal function => just its name, method => TYPE_FN.name
mut fn_name := f.name
if f.is_method {
fn_name = receiver_type.replace('*', '') + '_' + f.name
fn_name = receiver_type.replace('*', '') + '_' + f.name
//fn_name = '${receiver_type}_${f.name}'
}
// Generate tmp struct with args
@ -592,39 +592,39 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
}
fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type string) {
if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.mod != p.mod {
if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.mod != p.mod {
p.error('function `$f.name` is private')
}
p.calling_c = f.is_c
if f.is_c && !p.builtin_mod {
if f.name == 'free' {
p.error('use `free()` instead of `C.free()`')
p.error('use `free()` instead of `C.free()`')
} else if f.name == 'malloc' {
p.error('use `malloc()` instead of `C.malloc()`')
}
}
p.error('use `malloc()` instead of `C.malloc()`')
}
}
mut cgen_name := p.table.cgen_name(f)
p.next()
mut gen_type := ''
mut gen_type := ''
if p.tok == .lt {
p.check(.lt)
gen_type = p.check_name()
// run<T> => run_App
gen_type = p.check_name()
// run<T> => run_App
if gen_type == 'T' && p.cur_gen_type != '' {
gen_type = p.cur_gen_type
}
// `foo<Bar>()`
// If we are in the first pass, we need to add `Bar` type to the generic function `foo`,
// so that generic `foo`s body can be generated for each type in the second pass.
gen_type = p.cur_gen_type
}
// `foo<Bar>()`
// If we are in the first pass, we need to add `Bar` type to the generic function `foo`,
// so that generic `foo`s body can be generated for each type in the second pass.
if p.first_pass() {
println('registering $gen_type in $f.name fname=$f.name')
p.table.register_generic_fn_type(f.name, gen_type)
// Function bodies are skipped in the first passed, we only need to register the generic type here.
return
}
cgen_name += '_' + gen_type
println('registering $gen_type in $f.name fname=$f.name')
p.table.register_generic_fn_type(f.name, gen_type)
// Function bodies are skipped in the first passed, we only need to register the generic type here.
return
}
cgen_name += '_' + gen_type
p.check(.gt)
}
}
// if p.pref.is_prof {
// p.cur_fn.called_fns << cgen_name
// }
@ -642,10 +642,10 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin
if receiver.is_mut && !p.expr_var.is_mut {
println('$method_call recv=$receiver.name recv_mut=$receiver.is_mut')
p.error('`$p.expr_var.name` is immutable, declare it with `mut`')
}
}
if !p.expr_var.is_changed {
p.cur_fn.mark_var_changed(p.expr_var)
}
p.cur_fn.mark_var_changed(p.expr_var)
}
// if receiver is key_mut or a ref (&), generate & for the first arg
if receiver.ref || (receiver.is_mut && !receiver_type.contains('*')) {
method_call += '& /* ? */'
@ -664,7 +664,7 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin
}
p.cgen.set_placeholder(method_ph, '$cast $method_call')
}
// foo<Bar>()
// foo<Bar>()
p.fn_call_args(mut f)
p.gen(')')
p.calling_c = false
@ -675,14 +675,14 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin
// return an updated Fn object with args[] field set
fn (p mut Parser) fn_args(f mut Fn) {
p.check(.lpar)
defer { p.check(.rpar) }
defer { p.check(.rpar) }
if f.is_interface {
int_arg := Var {
typ: f.receiver_typ
}
f.args << int_arg
}
// `(int, string, int)`
// `(int, string, int)`
// Just register fn arg types
types_only := p.tok == .mul || (p.peek() == .comma && p.table.known_type(p.lit)) || p.peek() == .rpar// (int, string)
if types_only {
@ -719,19 +719,19 @@ fn (p mut Parser) fn_args(f mut Fn) {
}
mut typ := p.get_type()
if is_mut && is_primitive_type(typ) {
p.error('mutable arguments are only allowed for arrays, maps, and structs.' +
'\nreturn values instead: `foo(n mut int)` => `foo(n int) int`')
}
p.error('mutable arguments are only allowed for arrays, maps, and structs.' +
'\nreturn values instead: `foo(n mut int)` => `foo(n int) int`')
}
for name in names {
if !p.first_pass() && !p.table.known_type(typ) {
if !p.first_pass() && !p.table.known_type(typ) {
p.error('fn_args: unknown type $typ')
}
if is_mut {
if is_mut {
typ += '*'
}
v := Var {
name: name
typ: typ
typ: typ
is_arg: true
is_mut: is_mut
ptr: is_mut
@ -752,7 +752,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
}
}
// foo *(1, 2, 3, mut bar)*
// foo *(1, 2, 3, mut bar)*
fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
// p.gen('(')
// println('fn_call_args() name=$f.name args.len=$f.args.len')
@ -795,72 +795,72 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
break
}
ph := p.cgen.add_placeholder()
// `)` here means that not enough args were provided
// `)` here means that not enough args were provided
if p.tok == .rpar {
str_args := f.str_args(p.table)// TODO this is C args
p.error('not enough arguments in call to `$f.name ($str_args)`')
}
// If `arg` is mutable, the caller needs to provide `mut`:
// If `arg` is mutable, the caller needs to provide `mut`:
// `mut numbers := [1,2,3]; reverse(mut numbers);`
if arg.is_mut {
if p.tok != .key_mut && p.tok == .name {
mut dots_example := 'mut $p.lit'
mut dots_example := 'mut $p.lit'
if i > 0 {
dots_example = '.., ' + dots_example
}
dots_example = '.., ' + dots_example
}
if i < f.args.len - 1 {
dots_example = dots_example + ',..'
}
dots_example = dots_example + ',..'
}
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name($dots_example)`')
}
if p.peek() != .name {
p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`')
}
p.check(.key_mut)
var_name := p.lit
v := p.cur_fn.find_var(var_name)
if v.name == '' {
var_name := p.lit
v := p.cur_fn.find_var(var_name)
if v.name == '' {
p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`')
}
}
if !v.is_changed {
p.cur_fn.mark_var_changed(v)
}
}
p.expected_type = arg.typ
p.cur_fn.mark_var_changed(v)
}
}
p.expected_type = arg.typ
typ := p.bool_expression()
// Optimize `println`: replace it with `printf` to avoid extra allocations and
// function calls. `println(777)` => `printf("%d\n", 777)`
// (If we don't check for void, then V will compile `println(func())`)
// function calls. `println(777)` => `printf("%d\n", 777)`
// (If we don't check for void, then V will compile `println(func())`)
if i == 0 && f.name == 'println' && typ != 'string' && typ != 'void' {
T := p.table.find_type(typ)
$if !windows {
fmt := p.typ_to_fmt(typ, 0)
if fmt != '' {
p.cgen.resetln(p.cgen.cur_line.replace('println (', '/*opt*/printf ("' + fmt + '\\n", '))
continue
continue
}
}
if typ.ends_with('*') {
p.cgen.set_placeholder(ph, 'ptr_str(')
p.gen(')')
continue
continue
}
// Make sure this type has a `str()` method
if !T.has_method('str') {
// Arrays have automatic `str()` methods
// Arrays have automatic `str()` methods
if T.name.starts_with('array_') {
p.gen_array_str(mut T)
p.gen_array_str(mut T)
p.cgen.set_placeholder(ph, '${typ}_str(')
p.gen(')')
continue
}
continue
}
error_msg := ('`$typ` needs to have method `str() string` to be printable')
if T.fields.len > 0 {
mut index := p.cgen.cur_line.len - 1
for index > 0 && p.cgen.cur_line[index] != ` ` { index-- }
name := p.cgen.cur_line.right(index + 1)
if name == '}' {
p.error(error_msg)
p.error(error_msg)
}
p.cgen.resetln(p.cgen.cur_line.left(index))
p.scanner.create_type_string(T, name)
@ -868,7 +868,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
p.next()
return p.fn_call_args(mut f)
}
p.error(error_msg)
p.error(error_msg)
}
p.cgen.set_placeholder(ph, '${typ}_str(')
p.gen(')')
@ -893,18 +893,18 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
// TODO ptr hacks. DOOM hacks, fix please.
if !got.contains('*') && expected.contains('*') && got != 'voidptr' {
// Special case for mutable arrays. We can't `&` function results,
// have to use `(array[]){ expr }` hack.
if expected.starts_with('array_') && expected.ends_with('*') {
p.cgen.set_placeholder(ph, '& /*111*/ (array[]){')
p.gen('} ')
}
// have to use `(array[]){ expr }` hack.
if expected.starts_with('array_') && expected.ends_with('*') {
p.cgen.set_placeholder(ph, '& /*111*/ (array[]){')
p.gen('} ')
}
// println('\ne:"$expected" got:"$got"')
else if ! (expected == 'void*' && got == 'int') &&
! (expected == 'byte*' && got.contains(']byte')) &&
! (expected == 'byte*' && got == 'string') &&
//! (expected == 'void*' && got == 'array_int') {
! (expected == 'byte*' && got == 'byteptr') {
p.cgen.set_placeholder(ph, '& /*112 EXP:"$expected" GOT:"$got" */')
//! (expected == 'void*' && got == 'array_int') {
! (expected == 'byte*' && got == 'byteptr') {
p.cgen.set_placeholder(ph, '& /*112 EXP:"$expected" GOT:"$got" */')
}
}
}

View File

@ -57,23 +57,23 @@ fn (p mut Parser) gen_json_for_type(typ Type) {
p.table.register_fn(enc_fn)
// Code gen decoder
dec += '
//$t $dec_fn.name(cJSON* root) {
Option $dec_fn.name(cJSON* root, $t* res) {
// $t res;
//$t $dec_fn.name(cJSON* root) {
Option $dec_fn.name(cJSON* root, $t* res) {
// $t res;
if (!root) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
fprintf(stderr, "Error in decode() for $t error_ptr=: %%s\\n", error_ptr);
// printf("\\nbad js=%%s\\n", js.str);
// printf("\\nbad js=%%s\\n", js.str);
return v_error(tos2(error_ptr));
}
}
'
// Code gen encoder
enc += '
cJSON* $enc_fn.name($t val) {
cJSON* $enc_fn.name($t val) {
cJSON *o = cJSON_CreateObject();
string res = tos2("");
string res = tos2("");
'
// Handle arrays
if t.starts_with('array_') {
@ -144,7 +144,7 @@ fn (p mut Parser) decode_array(array_type string) string {
const cJSON *jsval = NULL;
cJSON_ArrayForEach(jsval, root)
{
$s
$s
array__push(res, &val);
}
'
@ -167,7 +167,7 @@ fn (p &Parser) encode_array(array_type string) string {
o = cJSON_CreateArray();
for (int i = 0; i < val.len; i++){
cJSON_AddItemToArray(o, $fn_name( (($typ*)val.data)[i] ));
}
}
'
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ mut:
fmt_out strings.Builder
fmt_indent int
fmt_line_empty bool
prev_tok Token
prev_tok Token
}
fn new_scanner(file_path string) *Scanner {
@ -207,7 +207,7 @@ fn (s Scanner) has_gone_over_line_end() bool {
fn (s mut Scanner) skip_whitespace() {
for s.pos < s.text.len && s.text[s.pos].is_white() {
// Count \r\n as one line
// Count \r\n as one line
if is_nl(s.text[s.pos]) && !s.expect('\r\n', s.pos-1) {
s.line_nr++
}
@ -216,10 +216,10 @@ fn (s mut Scanner) skip_whitespace() {
}
fn (s mut Scanner) scan() ScanRes {
if s.line_comment != '' {
if s.line_comment != '' {
//s.fgenln('// LOL "$s.line_comment"')
//s.line_comment = ''
}
//s.line_comment = ''
}
if s.started {
s.pos++
}
@ -388,11 +388,11 @@ fn (s mut Scanner) scan() ScanRes {
case `,`:
return scan_res(.comma, '')
case `@`:
s.pos++
s.pos++
name := s.ident_name()
if !is_key(name) {
s.error('@ must be used before keywords (e.g. `@type string`)')
}
s.error('@ must be used before keywords (e.g. `@type string`)')
}
return scan_res(.name, name)
case `\r`:
if nextc == `\n` {
@ -477,7 +477,7 @@ fn (s mut Scanner) scan() ScanRes {
else if nextc == `>` {
s.pos++
return scan_res(.arrow, '')
}
}
else {
return scan_res(.assign, '')
}
@ -515,7 +515,7 @@ fn (s mut Scanner) scan() ScanRes {
s.line_comment = s.text.substr(start + 1, s.pos)
s.line_comment = s.line_comment.trim_space()
s.fgenln('// ${s.prev_tok.str()} "$s.line_comment"')
// Skip the comment (return the next token)
// Skip the comment (return the next token)
return s.scan()
}
// Multiline comments
@ -553,13 +553,13 @@ fn (s mut Scanner) scan() ScanRes {
$if windows {
if c == `\0` {
return scan_res(.eof, '')
}
}
mut msg := 'invalid character `${c.str()}`'
}
}
mut msg := 'invalid character `${c.str()}`'
if c == `"` {
msg += ', use \' to denote strings'
}
s.error(msg)
msg += ', use \' to denote strings'
}
s.error(msg)
return scan_res(.eof, '')
}
@ -797,17 +797,17 @@ fn contains_capital(s string) bool {
}
// HTTPRequest bad
// HttpRequest good
// HttpRequest good
fn good_type_name(s string) bool {
if s.len < 4 {
return true
}
for i in 2 .. s.len {
return true
}
for i in 2 .. s.len {
if s[i].is_capital() && s[i-1].is_capital() && s[i-2].is_capital() {
return false
}
}
return true
}
return false
}
}
return true
}

View File

@ -4,15 +4,15 @@
module main
import math
import strings
import math
import strings
struct Table {
mut:
types []Type
consts []Var
fns map[string]Fn
generic_fns []GenTable //map[string]GenTable // generic_fns['listen_and_serve'] == ['Blog', 'Forum']
fns map[string]Fn
generic_fns []GenTable //map[string]GenTable // generic_fns['listen_and_serve'] == ['Blog', 'Forum']
obf_ids map[string]int // obf_ids['myfunction'] == 23
modules []string // List of all modules registered by the application
imports []string // List of all imports
@ -23,9 +23,9 @@ mut:
}
struct GenTable {
fn_name string
types []string
}
fn_name string
types []string
}
// Holds import information scoped to the parsed file
struct FileImportTable {
@ -36,8 +36,8 @@ mut:
}
enum AccessMod {
private // private immutable
private_mut // private mutable
private // private immutable
private_mut // private mutable
public // public immutable (readonly)
public_mut // public, but mutable only in this module
public_mut_mut // public and mutable both inside and outside (not recommended to use, that's why it's so verbose)
@ -54,13 +54,13 @@ mut:
is_c bool // C.FI.le
is_interface bool
is_enum bool
enum_vals []string
gen_types []string
enum_vals []string
gen_types []string
// This field is used for types that are not defined yet but are known to exist.
// It allows having things like `fn (f Foo) bar()` before `Foo` is defined.
// This information is needed in the first pass.
is_placeholder bool
gen_str bool // needs `.str()` method generation
gen_str bool // needs `.str()` method generation
}
// For debugging types
@ -109,12 +109,12 @@ fn (f Fn) str() string {
}
fn (t &Table) debug_fns() string {
mut s := strings.new_builder(1000)
mut s := strings.new_builder(1000)
for _, f in t.fns {
s.writeln(f.name)
}
return s.str()
}
s.writeln(f.name)
}
return s.str()
}
// fn (types array_Type) print_to_file(f string) {
// }
@ -124,23 +124,23 @@ const (
)
fn is_number_type(typ string) bool {
return typ in number_types
return typ in number_types
}
fn is_float_type(typ string) bool {
return typ in float_types
return typ in float_types
}
fn is_primitive_type(typ string) bool {
return is_number_type(typ) || typ == 'string'
}
return is_number_type(typ) || typ == 'string'
}
fn new_table(obfuscate bool) *Table {
mut t := &Table {
obf_ids: map[string]int
fns: map[string]Fn
//generic_fns: map[string]GenTable{}
generic_fns: []GenTable
obf_ids: map[string]int
fns: map[string]Fn
//generic_fns: map[string]GenTable{}
generic_fns: []GenTable
obfuscate: obfuscate
file_imports: []FileImportTable
}
@ -223,7 +223,7 @@ fn (t mut Table) register_const(name, typ, mod string, is_imported bool) {
typ: typ
is_const: true
is_import_const: is_imported
mod: mod
mod: mod
}
}
@ -234,17 +234,17 @@ fn (p mut Parser) register_global(name, typ string) {
typ: typ
is_const: true
is_global: true
mod: p.mod
is_mut: true
mod: p.mod
is_mut: true
}
}
fn (t mut Table) register_fn(new_fn Fn) {
t.fns[new_fn.name] = new_fn
t.fns[new_fn.name] = new_fn
}
fn (table &Table) known_type(typ_ string) bool {
mut typ := typ_
mut typ := typ_
// 'byte*' => look up 'byte', but don't mess up fns
if typ.ends_with('*') && !typ.contains(' ') {
typ = typ.left(typ.len - 1)
@ -258,16 +258,16 @@ fn (table &Table) known_type(typ_ string) bool {
}
fn (t &Table) find_fn(name string) Fn {
f := t.fns[name]
if !isnil(f.name.str) {
return f
}
f := t.fns[name]
if !isnil(f.name.str) {
return f
}
return Fn{}
}
fn (t &Table) known_fn(name string) bool {
f := t.find_fn(name)
return f.name != ''
f := t.find_fn(name)
return f.name != ''
}
fn (t &Table) known_const(name string) bool {
@ -318,10 +318,10 @@ if parent == 'array' {
mod = 'builtin'
}
*/
t.types << Type {
t.types << Type {
name: typ
parent: parent
//mod: mod
//mod: mod
}
}
@ -357,7 +357,7 @@ fn (t &Type) has_field(name string) bool {
}
fn (t &Type) has_enum_val(name string) bool {
return name in t.enum_vals
return name in t.enum_vals
}
fn (t &Type) find_field(name string) Var {
@ -425,7 +425,7 @@ fn (t &Type) find_method(name string) Fn {
return Fn{}
}
/*
/*
fn (t mut Type) add_gen_type(type_name string) {
// println('add_gen_type($s)')
if t.gen_types.contains(type_name) {
@ -433,7 +433,7 @@ fn (t mut Type) add_gen_type(type_name string) {
}
t.gen_types << type_name
}
*/
*/
fn (p &Parser) find_type(name string) &Type {
typ := p.table.find_type(name)
@ -444,7 +444,7 @@ fn (p &Parser) find_type(name string) &Type {
}
fn (t &Table) find_type(name_ string) *Type {
mut name := name_
mut name := name_
if name.ends_with('*') && !name.contains(' ') {
name = name.left(name.len - 1)
}
@ -458,8 +458,8 @@ fn (t &Table) find_type(name_ string) *Type {
}
fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
mut got := got_
mut expected := expected_
mut got := got_
mut expected := expected_
p.log('check types got="$got" exp="$expected" ')
if p.pref.translated {
return true
@ -505,13 +505,13 @@ fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
}
if got=='byte*' && expected=='byteptr' {
return true
}
}
if got=='int' && expected=='byte*' {
return true
}
//if got=='int' && expected=='voidptr*' {
//return true
//}
//return true
//}
// byteptr += int
if got=='int' && expected=='byteptr' {
return true
@ -593,7 +593,7 @@ fn type_default(typ string) string {
if typ.ends_with('*') {
return '0'
}
// User struct defined in another module.
// User struct defined in another module.
if typ.contains('__') {
return 'STRUCT_DEFAULT_VALUE'
}
@ -617,7 +617,7 @@ fn type_default(typ string) string {
case 'byteptr': return '0'
case 'voidptr': return '0'
}
return 'STRUCT_DEFAULT_VALUE'
return 'STRUCT_DEFAULT_VALUE'
}
// TODO PERF O(n)
@ -632,7 +632,7 @@ fn (t &Table) is_interface(name string) bool {
// Do we have fn main()?
fn (t &Table) main_exists() bool {
for _, f in t.fns {
for _, f in t.fns {
if f.name == 'main' {
return true
}
@ -713,51 +713,51 @@ fn (table &Table) cgen_name_type_pair(name, typ string) string {
}
fn is_valid_int_const(val, typ string) bool {
x := val.int()
x := val.int()
switch typ {
case 'byte', 'u8': return 0 <= x && x <= math.MaxU8
case 'u16': return 0 <= x && x <= math.MaxU16
//case 'u32': return 0 <= x && x <= math.MaxU32
//case 'u64': return 0 <= x && x <= math.MaxU64
//////////////
case 'i8': return math.MinI8 <= x && x <= math.MaxI8
case 'i16': return math.MinI16 <= x && x <= math.MaxI16
case 'int', 'i32': return math.MinI32 <= x && x <= math.MaxI32
//case 'i64':
//x64 := val.i64()
//return i64(-(1<<63)) <= x64 && x64 <= i64((1<<63)-1)
}
return true
case 'byte', 'u8': return 0 <= x && x <= math.MaxU8
case 'u16': return 0 <= x && x <= math.MaxU16
//case 'u32': return 0 <= x && x <= math.MaxU32
//case 'u64': return 0 <= x && x <= math.MaxU64
//////////////
case 'i8': return math.MinI8 <= x && x <= math.MaxI8
case 'i16': return math.MinI16 <= x && x <= math.MaxI16
case 'int', 'i32': return math.MinI32 <= x && x <= math.MaxI32
//case 'i64':
//x64 := val.i64()
//return i64(-(1<<63)) <= x64 && x64 <= i64((1<<63)-1)
}
return true
}
fn (t mut Table) register_generic_fn(fn_name string) {
t.generic_fns << GenTable{fn_name, []string}
}
fn (t mut Table) register_generic_fn(fn_name string) {
t.generic_fns << GenTable{fn_name, []string}
}
fn (t mut Table) fn_gen_types(fn_name string) []string {
fn (t mut Table) fn_gen_types(fn_name string) []string {
for _, f in t.generic_fns {
if f.fn_name == fn_name {
return f.types
}
}
}
}
panic('function $fn_name not found')
}
}
// `foo<Bar>()`
// fn_name == 'foo'
// typ == 'Bar'
fn (t mut Table) register_generic_fn_type(fn_name, typ string) {
// typ == 'Bar'
fn (t mut Table) register_generic_fn_type(fn_name, typ string) {
for i, f in t.generic_fns {
if f.fn_name == fn_name {
t.generic_fns[i].types << typ
return
}
}
}
t.generic_fns[i].types << typ
return
}
}
}
fn (p mut Parser) typ_to_fmt(typ string, level int) string {
t := p.table.find_type(typ)
if t.is_enum {
if t.is_enum {
return '%d'
}
switch typ {
@ -775,12 +775,12 @@ fn (p mut Parser) typ_to_fmt(typ string, level int) string {
case 'void': p.error('cannot interpolate this value')
default:
if typ.ends_with('*') {
return '%p'
}
return '%p'
}
}
if t.parent != '' && level == 0 {
return p.typ_to_fmt(t.parent, level+1)
}
if t.parent != '' && level == 0 {
return p.typ_to_fmt(t.parent, level+1)
}
return ''
}
@ -818,7 +818,7 @@ fn (table &Table) qualify_module(mod string, file_path string) string {
fn new_file_import_table(file_path string) *FileImportTable {
return &FileImportTable{
file_path: file_path
imports: map[string]string
imports: map[string]string
}
}
@ -831,7 +831,7 @@ fn (fit mut FileImportTable) register_import(mod string) {
}
fn (fit mut FileImportTable) register_alias(alias string, mod string) {
if alias in fit.imports {
if alias in fit.imports {
panic('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
}
if mod.contains('.internal.') {
@ -850,14 +850,14 @@ fn (fit mut FileImportTable) register_alias(alias string, mod string) {
}
fn (fit &FileImportTable) known_alias(alias string) bool {
return alias in fit.imports
return alias in fit.imports
}
fn (fit &FileImportTable) is_aliased(mod string) bool {
for _, val in fit.imports {
for _, val in fit.imports {
if val == mod {
return true
}
return true
}
}
return false
}

View File

@ -6,35 +6,35 @@ module main
enum Token {
eof
name // user
number // 123
str // 'foo'
str_inter // 'name=$user.name'
chartoken // `A`
name // user
number // 123
str // 'foo'
str_inter // 'name=$user.name'
chartoken // `A`
plus
minus
mul
div
mod
xor // ^
pipe // |
inc // ++
dec // --
and // &&
logical_or
not
xor // ^
pipe // |
inc // ++
dec // --
and // &&
logical_or
not
bit_not
question
comma
semicolon
colon
arrow // =>
arrow // =>
amp
hash
dollar
left_shift
righ_shift
//at // @
//at // @
// = := += -=
assign
decl_assign
@ -63,10 +63,10 @@ enum Token {
ge
le
// comments
//line_com
//mline_com
nl
dot
//line_com
//mline_com
nl
dot
dotdot
// keywords
keyword_beg
@ -77,8 +77,8 @@ enum Token {
key_case
key_const
key_continue
key_default
key_defer
key_default
key_defer
key_else
key_embed
key_enum
@ -87,26 +87,26 @@ enum Token {
func
key_global
key_go
key_goto
key_if
key_goto
key_if
key_import
key_import_const
key_in
key_interface
key_match
key_import_const
key_in
key_interface
key_match
key_module
key_mut
key_return
key_select
key_select
key_sizeof
key_struct
key_switch
key_switch
key_true
key_type
//typeof
key_type
//typeof
key_orelse
key_union
key_pub
key_pub
key_static
keyword_end
}
@ -114,7 +114,7 @@ enum Token {
// build_keys genereates a map with keywords' string values:
// Keywords['return'] == .key_return
fn build_keys() map[string]int {
mut res := map[string]int
mut res := map[string]int
for t := int(Token.keyword_beg) + 1; t < int(Token.keyword_end); t++ {
key := TokenStr[t]
res[key] = int(t)
@ -122,7 +122,7 @@ fn build_keys() map[string]int {
return res
}
// TODO remove once we have `enum Token { name('name') if('if') ... }`
// TODO remove once we have `enum Token { name('name') if('if') ... }`
fn build_token_str() []string {
mut s := [''; NrTokens]
s[Token.keyword_beg] = ''
@ -246,9 +246,9 @@ fn (t Token) str() string {
fn (t Token) is_decl() bool {
// TODO i
//return t in [.key_enum, .key_interface, .func, .typ, .key_const,
//return t in [.key_enum, .key_interface, .func, .typ, .key_const,
//.key_import_const, .key_struct, .key_pub, .eof]
return t == .key_enum || t == .key_interface || t == .func ||
return t == .key_enum || t == .key_interface || t == .func ||
t == .key_struct || t == .key_type ||
t == .key_const || t == .key_import_const || t == .key_pub || t == .eof
}
@ -256,7 +256,7 @@ fn (t Token) is_decl() bool {
const (
AssignTokens = [
Token.assign, Token.plus_assign, Token.minus_assign,
Token.mult_assign, Token.div_assign, Token.xor_assign,
Token.mult_assign, Token.div_assign, Token.xor_assign,
Token.mod_assign,
Token.or_assign, Token.and_assign, Token.righ_shift_assign,
Token.left_shift_assign

View File

@ -2,13 +2,13 @@
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module main
module main
import strings
import strings
// fmt helpers
fn (scanner mut Scanner) fgen(s_ string) {
mut s := s_
mut s := s_
if scanner.fmt_line_empty {
s = strings.repeat(`\t`, scanner.fmt_indent) + s
}
@ -17,7 +17,7 @@ fn (scanner mut Scanner) fgen(s_ string) {
}
fn (scanner mut Scanner) fgenln(s_ string) {
mut s := s_
mut s := s_
if scanner.fmt_line_empty {
s = strings.repeat(`\t`, scanner.fmt_indent) + s
}

View File

@ -6,7 +6,7 @@ module builtin
struct string {
//mut:
//hash_cache int
//hash_cache int
pub:
str byteptr
len int
@ -22,10 +22,10 @@ pub:
// For C strings only
fn C.strlen(s byteptr) int
fn todo() { }
fn todo() { }
// Converts a C string to a V string.
// String data is reused, not copied.
// Converts a C string to a V string.
// String data is reused, not copied.
pub fn tos(s byteptr, len int) string {
// This should never happen.
if isnil(s) {
@ -44,8 +44,8 @@ pub fn tos_clone(s byteptr) string {
return tos2(s).clone()
}
// Same as `tos`, but calculates the length. Called by `string(bytes)` casts.
// Used only internally.
// Same as `tos`, but calculates the length. Called by `string(bytes)` casts.
// Used only internally.
fn tos2(s byteptr) string {
if isnil(s) {
panic('tos2: nil string')
@ -67,12 +67,12 @@ pub fn (a string) clone() string {
return b
}
/*
/*
pub fn (s string) cstr() byteptr {
clone := s.clone()
return clone.str
}
*/
*/
pub fn (s string) replace(rep, with string) string {
if s.len == 0 || rep.len == 0 {
@ -285,7 +285,7 @@ pub fn (s string) split_single(delim byte) []string {
}
val := s.substr(start, i)
if val.len > 0 {
res << val
res << val
}
start = i + 1
}
@ -329,7 +329,7 @@ pub fn (s string) right(n int) string {
return s.substr(n, s.len)
}
// substr
// substr
pub fn (s string) substr(start, end int) string {
if start > end || start > s.len || end > s.len || start < 0 || end < 0 {
panic('substr($start, $end) out of bounds (len=$s.len)')
@ -345,12 +345,12 @@ pub fn (s string) substr(start, end int) string {
}
res.str[len] = `\0`
/*
/*
res := string {
str: s.str + start
len: len
}
*/
*/
return res
}
@ -531,16 +531,16 @@ pub fn (ar []int) contains(val int) bool {
return false
}
/*
/*
pub fn (a []string) to_c() voidptr {
mut res := malloc(sizeof(byteptr) * a.len)
mut res := malloc(sizeof(byteptr) * a.len)
for i := 0; i < a.len; i++ {
val := a[i]
res[i] = val.str
res[i] = val.str
}
return res
return res
}
*/
*/
fn is_space(c byte) bool {
return C.isspace(c)
@ -563,8 +563,8 @@ pub fn (s string) trim_space() string {
end--
}
if i > end + 1 {
return s
}
return s
}
res := s.substr(i, end + 1)
return res
}
@ -599,12 +599,12 @@ pub fn (s string) trim_left(cutset string) string {
pub fn (s string) trim_right(cutset string) string {
if s.len == 0 {
return s
}
mut pos := s.len - 1
return s
}
mut pos := s.len - 1
for s[pos] == cutset[0] {
pos--
}
pos--
}
return s.left(pos+1)
}
@ -743,14 +743,14 @@ pub fn (s string) free() {
free(s.str)
}
/*
/*
fn (arr []string) free() {
for s in arr {
s.free()
}
C.free(arr.data)
}
*/
*/
// all_before('23:34:45.234', '.') == '23:34:45'
pub fn (s string) all_before(dot string) string {
@ -848,14 +848,14 @@ pub fn (c byte) is_white() bool {
pub fn (s string) hash() int {
//mut h := s.hash_cache
mut h := 0
if h == 0 && s.len > 0 {
for c in s {
h = h * 31 + int(c)
//mut h := s.hash_cache
mut h := 0
if h == 0 && s.len > 0 {
for c in s {
h = h * 31 + int(c)
}
}
return h
}
return h
}
pub fn (s string) bytes() []byte {