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

new enum syntax; update the compiler (p.tok == .name)

This commit is contained in:
Alexander Medvednikov
2019-07-07 22:30:15 +02:00
parent 385f47c0cd
commit 26ef99293d
8 changed files with 835 additions and 834 deletions

View File

@ -114,7 +114,7 @@ fn new_fn(pkg 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 ')
is_pub := p.tok == PUB
is_pub := p.tok == .key_pub
is_live := p.attr == 'live' && !p.pref.is_so
if is_live && !p.pref.is_live {
p.error('run `v -live program.v` if you want to use [live] functions')
@ -124,15 +124,15 @@ fn (p mut Parser) fn_decl() {
}
p.returns = false
p.next()
mut f := new_fn(p.pkg, is_pub)
mut f := new_fn(p.mod, is_pub)
// Method receiver
mut receiver_typ := ''
if p.tok == LPAR {
if p.tok == .lpar {
f.is_method = true
p.check(LPAR)
p.check(.lpar)
receiver_name := p.check_name()
is_mut := p.tok == MUT
is_amp := p.tok == AMP
is_mut := p.tok == .key_mut
is_amp := p.tok == .amp
if is_mut || is_amp {
p.check_space(p.tok)
}
@ -142,9 +142,9 @@ fn (p mut Parser) fn_decl() {
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
}
// Don't allow modifying types from a different module
if !p.first_run() && !p.builtin_pkg && T.pkg != p.pkg {
println('T.pkg=$T.pkg')
println('pkg=$p.pkg')
if !p.first_run() && !p.builtin_pkg && T.mod != p.mod {
println('T.mod=$T.mod')
println('pkg=$p.mod')
p.error('cannot define new methods on non-local type `$receiver_typ`')
}
// (a *Foo) instead of (a mut Foo) is a common mistake
@ -156,7 +156,7 @@ fn (p mut Parser) fn_decl() {
if is_mut || is_amp {
receiver_typ += '*'
}
p.check(RPAR)
p.check(.rpar)
p.fspace()
receiver := Var {
name: receiver_name
@ -170,7 +170,7 @@ fn (p mut Parser) fn_decl() {
f.args << receiver
f.register_var(receiver)
}
if p.tok == PLUS || p.tok == MINUS || p.tok == MUL {
if p.tok == .plus || p.tok == .minus || p.tok == .mul {
f.name = p.tok.str()
p.next()
}
@ -178,14 +178,14 @@ 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_pkg && p.pref.build_mode == default_mode
// is_sig := p.pref.build_mode == default_mode && (p.builtin_pkg || p.file.contains(LANG_TMP))
is_sig := p.is_sig()
// println('\n\nfn decl !!is_sig=$is_sig name=$f.name $p.builtin_pkg')
if is_c {
p.check(DOT)
p.check(.dot)
f.name = p.check_name()
f.is_c = true
}
@ -198,7 +198,7 @@ fn (p mut Parser) fn_decl() {
}
}
// simple_name := f.name
// println('!SIMPLE=$simple_name')
// println('!SIMP.le=$simple_name')
// user.register() => User_register()
has_receiver := receiver_typ.len > 0
if receiver_typ != '' {
@ -206,7 +206,7 @@ fn (p mut Parser) fn_decl() {
}
// full pkg function name
// os.exit ==> os__exit()
if !is_c && !p.builtin_pkg && p.pkg != 'main' && receiver_typ.len == 0 {
if !is_c && !p.builtin_pkg && p.mod != 'main' && receiver_typ.len == 0 {
f.name = p.prepend_pkg(f.name)
}
if p.first_run() && p.table.known_fn(f.name) && receiver_typ.len == 0 {
@ -218,42 +218,42 @@ fn (p mut Parser) fn_decl() {
}
// Generic?
mut is_generic := false
if p.tok == LT {
if p.tok == .lt {
p.next()
gen_type := p.check_name()
if gen_type != 'T' {
p.error('only `T` is allowed as a generic type for now')
}
p.check(GT)
p.check(.gt)
is_generic = true
}
// Args (...)
p.fn_args(mut f)
// Returns an error?
if p.tok == NOT {
if p.tok == .not {
p.next()
f.returns_error = true
}
// Returns a type?
mut typ := 'void'
if p.tok == NAME || p.tok == MUL || p.tok == AMP || p.tok == LSBR ||
p.tok == QUESTION {
if p.tok == .name || p.tok == .mul || p.tok == .amp || p.tok == .lsbr ||
p.tok == .question {
p.fgen(' ')
// TODO In
// if p.tok in [ NAME, MUL, AMP, LSBR ] {
// if p.tok in [ .name, .mul, .amp, .lsbr ] {
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)// || (p.tok == NAME && p.peek() != LCBR))
(p.tok != .lcbr)// || (p.tok == .name && p.peek() != .lcbr))
if is_fn_header {
f.is_decl = true
// println('GOT fn header $f.name')
// println('.key_goT fn header $f.name')
}
// { required only in normal function declarations
if !is_c && !is_sig && !is_fn_header {
p.fgen(' ')
p.check(LCBR)
p.check(.lcbr)
}
// Register option ? type
if typ.starts_with('Option_') {
@ -262,7 +262,7 @@ fn (p mut Parser) fn_decl() {
// Register function
f.typ = typ
mut str_args := f.str_args(p.table)
// println('FN DECL $f.name typ=$f.typ str_args="$str_args"')
// println('FN .decL $f.name typ=$f.typ str_args="$str_args"')
// Special case for main() args
if f.name == 'main' && !has_receiver {
if str_args != '' || typ != 'void' {
@ -305,7 +305,7 @@ fn (p mut Parser) fn_decl() {
// println('fn decl !!!!!!! REG PH $receiver_typ')
ttyp := Type {
name: receiver_typ.replace('*', '')
pkg: p.pkg
mod: p.mod
is_placeholder: true
}
p.table.register_type2(ttyp)
@ -328,7 +328,7 @@ fn (p mut Parser) fn_decl() {
}
}
// Live code reloading? Load all fns from .so
if is_live && p.first_run() && p.pkg == 'main' {
if is_live && p.first_run() && p.mod == 'main' {
//println('ADDING SO FN $fn_name_cgen')
p.cgen.so_fns << fn_name_cgen
fn_name_cgen = '(* $fn_name_cgen )'
@ -374,7 +374,7 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
}
// println('is_c=$is_c name=$f.name')
if is_c || is_sig || is_fn_header {
// println('IS SIG RETURNING tok=${p.strtok()}')
// println('IS SIG .key_returnING tok=${p.strtok()}')
p.fgenln('\n')
return
}
@ -395,15 +395,15 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
p.error('$f.name must return "$typ"')
}
// {} closed correctly? scope_level should be 0
if p.pkg == 'main' {
if p.mod == 'main' {
// println(p.cur_fn.scope_level)
}
if p.cur_fn.scope_level > 2 {
// p.error('unclosed {')
}
// Make sure all vars in this function are used (only in main for now)
// if p.builtin_pkg || p.pkg == 'os' ||p.pkg=='http'{
if p.pkg != 'main' {
// if p.builtin_pkg || p.mod == 'os' ||p.mod=='http'{
if p.mod != 'main' {
p.genln('}')
p.fgenln('\n')
return
@ -442,7 +442,7 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
// println('\nfn_call $f.name is_method=$f.is_method receiver_type=$f.receiver_type')
// p.print_tok()
mut thread_name := ''
// Normal function => just its name, method => TYPE_FNNAME
// Normal function => just its name, method => TYPE_FN.name
mut fn_name := f.name
if f.is_method {
receiver_type = receiver_type.replace('*', '')
@ -454,7 +454,7 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
p.genln('$arg_struct_name * $tmp_struct = malloc(sizeof($arg_struct_name));')
mut arg_struct := 'typedef struct $arg_struct_name { '
p.next()
p.check(LPAR)
p.check(.lpar)
// str_args contains the args for the wrapper function:
// wrapper(arg_struct * arg) { fn("arg->a, arg->b"); }
mut str_args := ''
@ -473,7 +473,7 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
p.expression()
p.genln(';')
if i < f.args.len - 1 {
p.check(COMMA)
p.check(.comma)
str_args += ','
}
}
@ -486,7 +486,7 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
// Create thread object
tmp_nr := p.get_tmp_counter()
thread_name = '_thread$tmp_nr'
if p.os != WINDOWS {
if p.os != .windows {
p.genln('pthread_t $thread_name;')
}
tmp2 := p.get_tmp()
@ -495,17 +495,17 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
parg = ' $tmp_struct'
}
// Call the wrapper
if p.os == WINDOWS {
if p.os == .windows {
p.genln(' CreateThread(0,0, $wrapper_name, $parg, 0,0);')
}
else {
p.genln('int $tmp2 = pthread_create(& $thread_name, NULL, $wrapper_name, $parg);')
}
p.check(RPAR)
p.check(.rpar)
}
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.pkg != p.pkg {
if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.pkg != p.mod {
p.error('function `$f.name` is private')
}
p.calling_c = f.is_c
@ -533,9 +533,9 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin
receiver := f.args.first()
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')
p.error('`$p.expr_var.name` is imkey_mut')
}
// if receiver is mutable or a ref (&), generate & for the first arg
// if receiver is key_mut or a ref (&), generate & for the first arg
if receiver.ref || (receiver.is_mut && !receiver_type.contains('*')) {
method_call += '& /* ? */'
}
@ -566,8 +566,8 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin
// for declaration
// return an updated Fn object with args[] field set
fn (p mut Parser) fn_args(f mut Fn) {
p.check(LPAR)
// TODO defer p.check(RPAR)
p.check(.lpar)
// TODO defer p.check(.rpar)
if f.is_interface {
int_arg := Var {
typ: f.receiver_typ
@ -575,9 +575,9 @@ fn (p mut Parser) fn_args(f mut Fn) {
f.args << int_arg
}
// Just register fn arg types
types_only := p.tok == MUL || (p.peek() == COMMA && p.table.known_type(p.lit)) || p.peek() == RPAR// (int, string)
types_only := p.tok == .mul || (p.peek() == .comma && p.table.known_type(p.lit)) || p.peek() == .rpar// (int, string)
if types_only {
for p.tok != RPAR {
for p.tok != .rpar {
typ := p.get_type()
v := Var {
typ: typ
@ -587,24 +587,24 @@ fn (p mut Parser) fn_args(f mut Fn) {
}
// f.register_var(v)
f.args << v
if p.tok == COMMA {
if p.tok == .comma {
p.next()
}
}
}
// (a int, b,c string) syntax
for p.tok != RPAR {
for p.tok != .rpar {
mut names := [
p.check_name()
]
// a,b,c int syntax
for p.tok == COMMA {
p.check(COMMA)
for p.tok == .comma {
p.check(.comma)
p.fspace()
names << p.check_name()
}
p.fspace()
is_mut := p.tok == MUT
is_mut := p.tok == .key_mut
if is_mut {
p.next()
}
@ -628,17 +628,17 @@ fn (p mut Parser) fn_args(f mut Fn) {
f.register_var(v)
f.args << v
}
if p.tok == COMMA {
if p.tok == .comma {
p.next()
}
if p.tok == DOTDOT {
if p.tok == .dotdot {
f.args << Var {
name: '..'
}
p.next()
}
}
p.check(RPAR)
p.check(.rpar)
}
fn (p mut Parser) fn_call_args(f *Fn) *Fn {
@ -646,16 +646,16 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
// println('fn_call_args() name=$f.name args.len=$f.args.len')
// C func. # of args is not known
// if f.name.starts_with('c_') {
p.check(LPAR)
p.check(.lpar)
if f.is_c {
for p.tok != RPAR {
for p.tok != .rpar {
p.bool_expression()
if p.tok == COMMA {
if p.tok == .comma {
p.gen(', ')
p.check(COMMA)
p.check(.comma)
}
}
p.check(RPAR)
p.check(.rpar)
return f
}
// Receiver - first arg
@ -673,22 +673,27 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
break
}
ph := p.cgen.add_placeholder()
// ) here means not enough args were supplied
if p.tok == RPAR {
// `)` 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 key_mut, the caller needs to provide `mut`:
// `arr := [1,2,3]; reverse(mut arr);`
if arg.is_mut {
if p.tok != MUT {
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name(...mut a...)`')
if p.tok != .key_mut {
p.error('`$arg.name` is a key_mut argument, you need to provide `mut`: `$f.name(...mut a...)`')
}
if p.peek() != NAME {
p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`')
if p.peek() != .name {
p.error('`$arg.name` is a key_mut argument, you need to provide a variable to modify: `$f.name(... mut a...)`')
}
p.check(MUT)
p.check(.key_mut)
}
p.expected_type = arg.typ
//TT := p.table.find_type(arg.typ)
//if arg.typ.parent == 'int' {
//p.expected_type =
//}
typ := p.bool_expression()
// Optimize `println`: replace it with `printf` to avoid extra allocations and
// function calls. `println(777)` => `printf("%d\n", 777)`
@ -748,7 +753,7 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
if ! (expected == 'void*' && got == 'int') &&
! (expected == 'byte*' && got.contains(']byte')) &&
! (expected == 'byte*' && got == 'string') {
p.cgen.set_placeholder(ph, '& /*11 EXP:"$expected" GOT:"$got" */')
p.cgen.set_placeholder(ph, '& /*11 EXP:"$expected" .key_goT:"$got" */')
}
}
}
@ -767,10 +772,10 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
if i < f.args.len - 1 {
// Handle 0 args passed to varargs
is_vararg := i == f.args.len - 2 && f.args[i + 1].name == '..'
if p.tok != COMMA && !is_vararg {
if p.tok != .comma && !is_vararg {
p.error('wrong number of arguments for $i,$arg.name fn `$f.name`: expected $f.args.len, but got less')
}
if p.tok == COMMA {
if p.tok == .comma {
p.fgen(', ')
}
if !is_vararg {
@ -783,20 +788,19 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
if f.args.len > 0 {
last_arg := f.args.last()
if last_arg.name == '..' {
println('GOT VAR ARGS AFTER')
for p.tok != RPAR {
if p.tok == COMMA {
for p.tok != .rpar {
if p.tok == .comma {
p.gen(',')
p.check(COMMA)
p.check(.comma)
}
p.bool_expression()
}
}
}
if p.tok == COMMA {
if p.tok == .comma {
p.error('wrong number of arguments for fn `$f.name`: expected $f.args.len, but got more')
}
p.check(RPAR)
p.check(.rpar)
// p.gen(')')
}