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:
parent
385f47c0cd
commit
26ef99293d
@ -45,7 +45,7 @@ fn new_cgen(out_name_c string) *CGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) genln(s string) {
|
fn (g mut CGen) genln(s string) {
|
||||||
if g.nogen || g.run == RUN_DECLS {
|
if g.nogen || g.run == .decl {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if g.is_tmp {
|
if g.is_tmp {
|
||||||
@ -61,7 +61,7 @@ fn (g mut CGen) genln(s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) gen(s string) {
|
fn (g mut CGen) gen(s string) {
|
||||||
if g.nogen || g.run == RUN_DECLS {
|
if g.nogen || g.run == .decl {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if g.is_tmp {
|
if g.is_tmp {
|
||||||
|
152
compiler/fn.v
152
compiler/fn.v
@ -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.
|
// Function signatures are added to the top of the .c file in the first run.
|
||||||
fn (p mut Parser) fn_decl() {
|
fn (p mut Parser) fn_decl() {
|
||||||
p.fgen('fn ')
|
p.fgen('fn ')
|
||||||
is_pub := p.tok == PUB
|
is_pub := p.tok == .key_pub
|
||||||
is_live := p.attr == 'live' && !p.pref.is_so
|
is_live := p.attr == 'live' && !p.pref.is_so
|
||||||
if is_live && !p.pref.is_live {
|
if is_live && !p.pref.is_live {
|
||||||
p.error('run `v -live program.v` if you want to use [live] functions')
|
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.returns = false
|
||||||
p.next()
|
p.next()
|
||||||
mut f := new_fn(p.pkg, is_pub)
|
mut f := new_fn(p.mod, is_pub)
|
||||||
// Method receiver
|
// Method receiver
|
||||||
mut receiver_typ := ''
|
mut receiver_typ := ''
|
||||||
if p.tok == LPAR {
|
if p.tok == .lpar {
|
||||||
f.is_method = true
|
f.is_method = true
|
||||||
p.check(LPAR)
|
p.check(.lpar)
|
||||||
receiver_name := p.check_name()
|
receiver_name := p.check_name()
|
||||||
is_mut := p.tok == MUT
|
is_mut := p.tok == .key_mut
|
||||||
is_amp := p.tok == AMP
|
is_amp := p.tok == .amp
|
||||||
if is_mut || is_amp {
|
if is_mut || is_amp {
|
||||||
p.check_space(p.tok)
|
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)')
|
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
|
||||||
}
|
}
|
||||||
// Don't allow modifying types from a different module
|
// Don't allow modifying types from a different module
|
||||||
if !p.first_run() && !p.builtin_pkg && T.pkg != p.pkg {
|
if !p.first_run() && !p.builtin_pkg && T.mod != p.mod {
|
||||||
println('T.pkg=$T.pkg')
|
println('T.mod=$T.mod')
|
||||||
println('pkg=$p.pkg')
|
println('pkg=$p.mod')
|
||||||
p.error('cannot define new methods on non-local type `$receiver_typ`')
|
p.error('cannot define new methods on non-local type `$receiver_typ`')
|
||||||
}
|
}
|
||||||
// (a *Foo) instead of (a mut Foo) is a common mistake
|
// (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 {
|
if is_mut || is_amp {
|
||||||
receiver_typ += '*'
|
receiver_typ += '*'
|
||||||
}
|
}
|
||||||
p.check(RPAR)
|
p.check(.rpar)
|
||||||
p.fspace()
|
p.fspace()
|
||||||
receiver := Var {
|
receiver := Var {
|
||||||
name: receiver_name
|
name: receiver_name
|
||||||
@ -170,7 +170,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
f.args << receiver
|
f.args << receiver
|
||||||
f.register_var(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()
|
f.name = p.tok.str()
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
@ -178,14 +178,14 @@ fn (p mut Parser) fn_decl() {
|
|||||||
f.name = p.check_name()
|
f.name = p.check_name()
|
||||||
}
|
}
|
||||||
// C function header def? (fn C.NSMakeRect(int,int,int,int))
|
// 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
|
// Just fn signature? only builtin.v + default build mode
|
||||||
// is_sig := p.builtin_pkg && p.pref.build_mode == default_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.pref.build_mode == default_mode && (p.builtin_pkg || p.file.contains(LANG_TMP))
|
||||||
is_sig := p.is_sig()
|
is_sig := p.is_sig()
|
||||||
// println('\n\nfn decl !!is_sig=$is_sig name=$f.name $p.builtin_pkg')
|
// println('\n\nfn decl !!is_sig=$is_sig name=$f.name $p.builtin_pkg')
|
||||||
if is_c {
|
if is_c {
|
||||||
p.check(DOT)
|
p.check(.dot)
|
||||||
f.name = p.check_name()
|
f.name = p.check_name()
|
||||||
f.is_c = true
|
f.is_c = true
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// simple_name := f.name
|
// simple_name := f.name
|
||||||
// println('!SIMPLE=$simple_name')
|
// println('!SIMP.le=$simple_name')
|
||||||
// user.register() => User_register()
|
// user.register() => User_register()
|
||||||
has_receiver := receiver_typ.len > 0
|
has_receiver := receiver_typ.len > 0
|
||||||
if receiver_typ != '' {
|
if receiver_typ != '' {
|
||||||
@ -206,7 +206,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
// full pkg function name
|
// full pkg function name
|
||||||
// os.exit ==> os__exit()
|
// 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)
|
f.name = p.prepend_pkg(f.name)
|
||||||
}
|
}
|
||||||
if p.first_run() && p.table.known_fn(f.name) && receiver_typ.len == 0 {
|
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?
|
// Generic?
|
||||||
mut is_generic := false
|
mut is_generic := false
|
||||||
if p.tok == LT {
|
if p.tok == .lt {
|
||||||
p.next()
|
p.next()
|
||||||
gen_type := p.check_name()
|
gen_type := p.check_name()
|
||||||
if gen_type != 'T' {
|
if gen_type != 'T' {
|
||||||
p.error('only `T` is allowed as a generic type for now')
|
p.error('only `T` is allowed as a generic type for now')
|
||||||
}
|
}
|
||||||
p.check(GT)
|
p.check(.gt)
|
||||||
is_generic = true
|
is_generic = true
|
||||||
}
|
}
|
||||||
// Args (...)
|
// Args (...)
|
||||||
p.fn_args(mut f)
|
p.fn_args(mut f)
|
||||||
// Returns an error?
|
// Returns an error?
|
||||||
if p.tok == NOT {
|
if p.tok == .not {
|
||||||
p.next()
|
p.next()
|
||||||
f.returns_error = true
|
f.returns_error = true
|
||||||
}
|
}
|
||||||
// Returns a type?
|
// Returns a type?
|
||||||
mut typ := 'void'
|
mut typ := 'void'
|
||||||
if p.tok == NAME || p.tok == MUL || p.tok == AMP || p.tok == LSBR ||
|
if p.tok == .name || p.tok == .mul || p.tok == .amp || p.tok == .lsbr ||
|
||||||
p.tok == QUESTION {
|
p.tok == .question {
|
||||||
p.fgen(' ')
|
p.fgen(' ')
|
||||||
// TODO In
|
// TODO In
|
||||||
// if p.tok in [ NAME, MUL, AMP, LSBR ] {
|
// if p.tok in [ .name, .mul, .amp, .lsbr ] {
|
||||||
typ = p.get_type()
|
typ = p.get_type()
|
||||||
}
|
}
|
||||||
// Translated C code can have empty functions (just definitions)
|
// Translated C code can have empty functions (just definitions)
|
||||||
is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) &&
|
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 {
|
if is_fn_header {
|
||||||
f.is_decl = true
|
f.is_decl = true
|
||||||
// println('GOT fn header $f.name')
|
// println('.key_goT fn header $f.name')
|
||||||
}
|
}
|
||||||
// { required only in normal function declarations
|
// { required only in normal function declarations
|
||||||
if !is_c && !is_sig && !is_fn_header {
|
if !is_c && !is_sig && !is_fn_header {
|
||||||
p.fgen(' ')
|
p.fgen(' ')
|
||||||
p.check(LCBR)
|
p.check(.lcbr)
|
||||||
}
|
}
|
||||||
// Register option ? type
|
// Register option ? type
|
||||||
if typ.starts_with('Option_') {
|
if typ.starts_with('Option_') {
|
||||||
@ -262,7 +262,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
// Register function
|
// Register function
|
||||||
f.typ = typ
|
f.typ = typ
|
||||||
mut str_args := f.str_args(p.table)
|
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
|
// Special case for main() args
|
||||||
if f.name == 'main' && !has_receiver {
|
if f.name == 'main' && !has_receiver {
|
||||||
if str_args != '' || typ != 'void' {
|
if str_args != '' || typ != 'void' {
|
||||||
@ -305,7 +305,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
// println('fn decl !!!!!!! REG PH $receiver_typ')
|
// println('fn decl !!!!!!! REG PH $receiver_typ')
|
||||||
ttyp := Type {
|
ttyp := Type {
|
||||||
name: receiver_typ.replace('*', '')
|
name: receiver_typ.replace('*', '')
|
||||||
pkg: p.pkg
|
mod: p.mod
|
||||||
is_placeholder: true
|
is_placeholder: true
|
||||||
}
|
}
|
||||||
p.table.register_type2(ttyp)
|
p.table.register_type2(ttyp)
|
||||||
@ -328,7 +328,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Live code reloading? Load all fns from .so
|
// 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')
|
//println('ADDING SO FN $fn_name_cgen')
|
||||||
p.cgen.so_fns << fn_name_cgen
|
p.cgen.so_fns << fn_name_cgen
|
||||||
fn_name_cgen = '(* $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')
|
// println('is_c=$is_c name=$f.name')
|
||||||
if is_c || is_sig || is_fn_header {
|
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')
|
p.fgenln('\n')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -395,15 +395,15 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
|
|||||||
p.error('$f.name must return "$typ"')
|
p.error('$f.name must return "$typ"')
|
||||||
}
|
}
|
||||||
// {} closed correctly? scope_level should be 0
|
// {} closed correctly? scope_level should be 0
|
||||||
if p.pkg == 'main' {
|
if p.mod == 'main' {
|
||||||
// println(p.cur_fn.scope_level)
|
// println(p.cur_fn.scope_level)
|
||||||
}
|
}
|
||||||
if p.cur_fn.scope_level > 2 {
|
if p.cur_fn.scope_level > 2 {
|
||||||
// p.error('unclosed {')
|
// p.error('unclosed {')
|
||||||
}
|
}
|
||||||
// Make sure all vars in this function are used (only in main for now)
|
// 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.builtin_pkg || p.mod == 'os' ||p.mod=='http'{
|
||||||
if p.pkg != 'main' {
|
if p.mod != 'main' {
|
||||||
p.genln('}')
|
p.genln('}')
|
||||||
p.fgenln('\n')
|
p.fgenln('\n')
|
||||||
return
|
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')
|
// println('\nfn_call $f.name is_method=$f.is_method receiver_type=$f.receiver_type')
|
||||||
// p.print_tok()
|
// p.print_tok()
|
||||||
mut thread_name := ''
|
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
|
mut fn_name := f.name
|
||||||
if f.is_method {
|
if f.is_method {
|
||||||
receiver_type = receiver_type.replace('*', '')
|
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));')
|
p.genln('$arg_struct_name * $tmp_struct = malloc(sizeof($arg_struct_name));')
|
||||||
mut arg_struct := 'typedef struct $arg_struct_name { '
|
mut arg_struct := 'typedef struct $arg_struct_name { '
|
||||||
p.next()
|
p.next()
|
||||||
p.check(LPAR)
|
p.check(.lpar)
|
||||||
// str_args contains the args for the wrapper function:
|
// str_args contains the args for the wrapper function:
|
||||||
// wrapper(arg_struct * arg) { fn("arg->a, arg->b"); }
|
// wrapper(arg_struct * arg) { fn("arg->a, arg->b"); }
|
||||||
mut str_args := ''
|
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.expression()
|
||||||
p.genln(';')
|
p.genln(';')
|
||||||
if i < f.args.len - 1 {
|
if i < f.args.len - 1 {
|
||||||
p.check(COMMA)
|
p.check(.comma)
|
||||||
str_args += ','
|
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
|
// Create thread object
|
||||||
tmp_nr := p.get_tmp_counter()
|
tmp_nr := p.get_tmp_counter()
|
||||||
thread_name = '_thread$tmp_nr'
|
thread_name = '_thread$tmp_nr'
|
||||||
if p.os != WINDOWS {
|
if p.os != .windows {
|
||||||
p.genln('pthread_t $thread_name;')
|
p.genln('pthread_t $thread_name;')
|
||||||
}
|
}
|
||||||
tmp2 := p.get_tmp()
|
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'
|
parg = ' $tmp_struct'
|
||||||
}
|
}
|
||||||
// Call the wrapper
|
// Call the wrapper
|
||||||
if p.os == WINDOWS {
|
if p.os == .windows {
|
||||||
p.genln(' CreateThread(0,0, $wrapper_name, $parg, 0,0);')
|
p.genln(' CreateThread(0,0, $wrapper_name, $parg, 0,0);')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.genln('int $tmp2 = pthread_create(& $thread_name, NULL, $wrapper_name, $parg);')
|
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) {
|
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.error('function `$f.name` is private')
|
||||||
}
|
}
|
||||||
p.calling_c = f.is_c
|
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()
|
receiver := f.args.first()
|
||||||
if receiver.is_mut && !p.expr_var.is_mut {
|
if receiver.is_mut && !p.expr_var.is_mut {
|
||||||
println('$method_call recv=$receiver.name recv_mut=$receiver.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('*')) {
|
if receiver.ref || (receiver.is_mut && !receiver_type.contains('*')) {
|
||||||
method_call += '& /* ? */'
|
method_call += '& /* ? */'
|
||||||
}
|
}
|
||||||
@ -566,8 +566,8 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin
|
|||||||
// for declaration
|
// for declaration
|
||||||
// return an updated Fn object with args[] field set
|
// return an updated Fn object with args[] field set
|
||||||
fn (p mut Parser) fn_args(f mut Fn) {
|
fn (p mut Parser) fn_args(f mut Fn) {
|
||||||
p.check(LPAR)
|
p.check(.lpar)
|
||||||
// TODO defer p.check(RPAR)
|
// TODO defer p.check(.rpar)
|
||||||
if f.is_interface {
|
if f.is_interface {
|
||||||
int_arg := Var {
|
int_arg := Var {
|
||||||
typ: f.receiver_typ
|
typ: f.receiver_typ
|
||||||
@ -575,9 +575,9 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
|||||||
f.args << int_arg
|
f.args << int_arg
|
||||||
}
|
}
|
||||||
// Just register fn arg types
|
// 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 {
|
if types_only {
|
||||||
for p.tok != RPAR {
|
for p.tok != .rpar {
|
||||||
typ := p.get_type()
|
typ := p.get_type()
|
||||||
v := Var {
|
v := Var {
|
||||||
typ: typ
|
typ: typ
|
||||||
@ -587,24 +587,24 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
|||||||
}
|
}
|
||||||
// f.register_var(v)
|
// f.register_var(v)
|
||||||
f.args << v
|
f.args << v
|
||||||
if p.tok == COMMA {
|
if p.tok == .comma {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (a int, b,c string) syntax
|
// (a int, b,c string) syntax
|
||||||
for p.tok != RPAR {
|
for p.tok != .rpar {
|
||||||
mut names := [
|
mut names := [
|
||||||
p.check_name()
|
p.check_name()
|
||||||
]
|
]
|
||||||
// a,b,c int syntax
|
// a,b,c int syntax
|
||||||
for p.tok == COMMA {
|
for p.tok == .comma {
|
||||||
p.check(COMMA)
|
p.check(.comma)
|
||||||
p.fspace()
|
p.fspace()
|
||||||
names << p.check_name()
|
names << p.check_name()
|
||||||
}
|
}
|
||||||
p.fspace()
|
p.fspace()
|
||||||
is_mut := p.tok == MUT
|
is_mut := p.tok == .key_mut
|
||||||
if is_mut {
|
if is_mut {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
@ -628,17 +628,17 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
|||||||
f.register_var(v)
|
f.register_var(v)
|
||||||
f.args << v
|
f.args << v
|
||||||
}
|
}
|
||||||
if p.tok == COMMA {
|
if p.tok == .comma {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
if p.tok == DOTDOT {
|
if p.tok == .dotdot {
|
||||||
f.args << Var {
|
f.args << Var {
|
||||||
name: '..'
|
name: '..'
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(RPAR)
|
p.check(.rpar)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
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')
|
// println('fn_call_args() name=$f.name args.len=$f.args.len')
|
||||||
// C func. # of args is not known
|
// C func. # of args is not known
|
||||||
// if f.name.starts_with('c_') {
|
// if f.name.starts_with('c_') {
|
||||||
p.check(LPAR)
|
p.check(.lpar)
|
||||||
if f.is_c {
|
if f.is_c {
|
||||||
for p.tok != RPAR {
|
for p.tok != .rpar {
|
||||||
p.bool_expression()
|
p.bool_expression()
|
||||||
if p.tok == COMMA {
|
if p.tok == .comma {
|
||||||
p.gen(', ')
|
p.gen(', ')
|
||||||
p.check(COMMA)
|
p.check(.comma)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(RPAR)
|
p.check(.rpar)
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
// Receiver - first arg
|
// Receiver - first arg
|
||||||
@ -673,22 +673,27 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
ph := p.cgen.add_placeholder()
|
ph := p.cgen.add_placeholder()
|
||||||
// ) here means not enough args were supplied
|
// `)` here means that not enough args were provided
|
||||||
if p.tok == RPAR {
|
if p.tok == .rpar {
|
||||||
str_args := f.str_args(p.table)// TODO this is C args
|
str_args := f.str_args(p.table)// TODO this is C args
|
||||||
p.error('not enough arguments in call to `$f.name ($str_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);`
|
// `arr := [1,2,3]; reverse(mut arr);`
|
||||||
if arg.is_mut {
|
if arg.is_mut {
|
||||||
if p.tok != MUT {
|
if p.tok != .key_mut {
|
||||||
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name(...mut a...)`')
|
p.error('`$arg.name` is a key_mut argument, you need to provide `mut`: `$f.name(...mut a...)`')
|
||||||
}
|
}
|
||||||
if p.peek() != NAME {
|
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.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()
|
typ := p.bool_expression()
|
||||||
// Optimize `println`: replace it with `printf` to avoid extra allocations and
|
// Optimize `println`: replace it with `printf` to avoid extra allocations and
|
||||||
// function calls. `println(777)` => `printf("%d\n", 777)`
|
// 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') &&
|
if ! (expected == 'void*' && got == 'int') &&
|
||||||
! (expected == 'byte*' && got.contains(']byte')) &&
|
! (expected == 'byte*' && got.contains(']byte')) &&
|
||||||
! (expected == 'byte*' && got == 'string') {
|
! (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 {
|
if i < f.args.len - 1 {
|
||||||
// Handle 0 args passed to varargs
|
// Handle 0 args passed to varargs
|
||||||
is_vararg := i == f.args.len - 2 && f.args[i + 1].name == '..'
|
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')
|
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(', ')
|
p.fgen(', ')
|
||||||
}
|
}
|
||||||
if !is_vararg {
|
if !is_vararg {
|
||||||
@ -783,20 +788,19 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
|||||||
if f.args.len > 0 {
|
if f.args.len > 0 {
|
||||||
last_arg := f.args.last()
|
last_arg := f.args.last()
|
||||||
if last_arg.name == '..' {
|
if last_arg.name == '..' {
|
||||||
println('GOT VAR ARGS AFTER')
|
for p.tok != .rpar {
|
||||||
for p.tok != RPAR {
|
if p.tok == .comma {
|
||||||
if p.tok == COMMA {
|
|
||||||
p.gen(',')
|
p.gen(',')
|
||||||
p.check(COMMA)
|
p.check(.comma)
|
||||||
}
|
}
|
||||||
p.bool_expression()
|
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.error('wrong number of arguments for fn `$f.name`: expected $f.args.len, but got more')
|
||||||
}
|
}
|
||||||
p.check(RPAR)
|
p.check(.rpar)
|
||||||
// p.gen(')')
|
// p.gen(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ fn (p mut Parser) gen_json_for_type(typ Type) {
|
|||||||
// println('gen_json_for_type( $typ.name )')
|
// println('gen_json_for_type( $typ.name )')
|
||||||
// Register decoder fn
|
// Register decoder fn
|
||||||
mut dec_fn := Fn {
|
mut dec_fn := Fn {
|
||||||
pkg: p.pkg
|
pkg: p.mod
|
||||||
typ: 'Option_$typ.name'
|
typ: 'Option_$typ.name'
|
||||||
name: js_dec_name(t)
|
name: js_dec_name(t)
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ fn (p mut Parser) gen_json_for_type(typ Type) {
|
|||||||
p.table.register_fn(dec_fn)
|
p.table.register_fn(dec_fn)
|
||||||
// Register encoder fn
|
// Register encoder fn
|
||||||
mut enc_fn := Fn {
|
mut enc_fn := Fn {
|
||||||
pkg: p.pkg
|
pkg: p.mod
|
||||||
typ: 'cJSON*'
|
typ: 'cJSON*'
|
||||||
name: js_enc_name(t)
|
name: js_enc_name(t)
|
||||||
}
|
}
|
||||||
|
@ -32,35 +32,31 @@ const (
|
|||||||
TmpPath = vtmp_path()
|
TmpPath = vtmp_path()
|
||||||
)
|
)
|
||||||
|
|
||||||
enum Os {
|
enum OS {
|
||||||
MAC
|
mac
|
||||||
LINUX
|
linux
|
||||||
WINDOWS
|
windows
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Pass {
|
enum Pass {
|
||||||
// A very short pass that only looks at imports in the begginning of each file
|
// A very short pass that only looks at imports in the begginning of each file
|
||||||
RUN_IMPORTS
|
imports
|
||||||
// First pass, only parses and saves declarations (fn signatures, consts, types).
|
// First pass, only parses and saves declarations (fn signatures, consts, types).
|
||||||
// Skips function bodies.
|
// Skips function bodies.
|
||||||
// We need this because in V things can be used before they are declared.
|
// We need this because in V things can be used before they are declared.
|
||||||
RUN_DECLS
|
decl
|
||||||
// Second pass, parses function bodies and generates C or machine code.
|
// Second pass, parses function bodies and generates C or machine code.
|
||||||
RUN_MAIN
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO rename to:
|
|
||||||
enum Pass {
|
|
||||||
imports
|
|
||||||
decls
|
|
||||||
main
|
main
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
fn mykek(o OS) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct V {
|
struct V {
|
||||||
mut:
|
mut:
|
||||||
os Os // the OS to build for
|
os OS // the OS to build for
|
||||||
out_name_c string // name of the temporary C file
|
out_name_c string // name of the temporary C file
|
||||||
files []string // all V files that need to be parsed and compiled
|
files []string // all V files that need to be parsed and compiled
|
||||||
dir string // directory (or file) being compiled (TODO rename to path?)
|
dir string // directory (or file) being compiled (TODO rename to path?)
|
||||||
@ -125,7 +121,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Just fmt and exit
|
// Just fmt and exit
|
||||||
if args.contains('fmt') {
|
if 'fmt' in args {
|
||||||
file := args.last()
|
file := args.last()
|
||||||
if !os.file_exists(file) {
|
if !os.file_exists(file) {
|
||||||
println('"$file" does not exist')
|
println('"$file" does not exist')
|
||||||
@ -138,7 +134,7 @@ fn main() {
|
|||||||
println('vfmt is temporarily disabled')
|
println('vfmt is temporarily disabled')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// V with no args? REPL
|
// No args? REPL
|
||||||
if args.len < 2 || (args.len == 2 && args[1] == '-') {
|
if args.len < 2 || (args.len == 2 && args[1] == '-') {
|
||||||
run_repl()
|
run_repl()
|
||||||
return
|
return
|
||||||
@ -149,7 +145,7 @@ fn main() {
|
|||||||
println(args)
|
println(args)
|
||||||
}
|
}
|
||||||
// Generate the docs and exit
|
// Generate the docs and exit
|
||||||
if args.contains('doc') {
|
if 'doc' in args {
|
||||||
// v.gen_doc_html_for_module(args.last())
|
// v.gen_doc_html_for_module(args.last())
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
@ -167,11 +163,11 @@ fn (v mut V) compile() {
|
|||||||
}
|
}
|
||||||
// First pass (declarations)
|
// First pass (declarations)
|
||||||
for file in v.files {
|
for file in v.files {
|
||||||
mut p := v.new_parser(file, RUN_DECLS)
|
mut p := v.new_parser(file, Pass.decl)
|
||||||
p.parse()
|
p.parse()
|
||||||
}
|
}
|
||||||
// Main pass
|
// Main pass
|
||||||
cgen.run = RUN_MAIN
|
cgen.run = Pass.main
|
||||||
if v.pref.is_play {
|
if v.pref.is_play {
|
||||||
cgen.genln('#define VPLAY (1) ')
|
cgen.genln('#define VPLAY (1) ')
|
||||||
}
|
}
|
||||||
@ -233,13 +229,13 @@ typedef map map_string;
|
|||||||
#define false 0
|
#define false 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//============================== HELPER C MACROS =============================*/
|
//============================== HELPER C.MACROS =============================*/
|
||||||
|
|
||||||
#define _PUSH(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push(arr, &tmp);}
|
#define _PUSH(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push(arr, &tmp);}
|
||||||
#define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push_many(arr, tmp.data, tmp.len);}
|
#define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push_many(arr, tmp.data, tmp.len);}
|
||||||
#define _IN(typ, val, arr) array_##typ##_contains(arr, val)
|
#define _IN(typ, val, arr) array_##typ##_contains(arr, val)
|
||||||
#define ALLOC_INIT(type, ...) (type *)memdup((type[]){ __VA_ARGS__ }, sizeof(type))
|
#define ALLOC_INIT(type, ...) (type *)memdup((type[]){ __VA_ARGS__ }, sizeof(type))
|
||||||
#define UTF8_CHAR_LEN( byte ) (( 0xE5000000 >> (( byte >> 3 ) & 0x1e )) & 3 ) + 1
|
#define UTF8_.chartoken_.leN( byte ) (( 0xE5000000 >> (( byte >> 3 ) & 0x1e )) & 3 ) + 1
|
||||||
|
|
||||||
//================================== GLOBALS =================================*/
|
//================================== GLOBALS =================================*/
|
||||||
//int V_ZERO = 0;
|
//int V_ZERO = 0;
|
||||||
@ -249,7 +245,7 @@ void reload_so();
|
|||||||
void init_consts();')
|
void init_consts();')
|
||||||
imports_json := v.table.imports.contains('json')
|
imports_json := v.table.imports.contains('json')
|
||||||
// TODO remove global UI hack
|
// TODO remove global UI hack
|
||||||
if v.os == MAC && ((v.pref.build_mode == .embed_vlib && v.table.imports.contains('ui')) ||
|
if v.os == .mac && ((v.pref.build_mode == .embed_vlib && v.table.imports.contains('ui')) ||
|
||||||
(v.pref.build_mode == .build && v.dir.contains('/ui'))) {
|
(v.pref.build_mode == .build && v.dir.contains('/ui'))) {
|
||||||
cgen.genln('id defaultFont = 0; // main.v')
|
cgen.genln('id defaultFont = 0; // main.v')
|
||||||
}
|
}
|
||||||
@ -284,7 +280,7 @@ void init_consts();')
|
|||||||
cgen.genln('this line will be replaced with definitions')
|
cgen.genln('this line will be replaced with definitions')
|
||||||
defs_pos := cgen.lines.len - 1
|
defs_pos := cgen.lines.len - 1
|
||||||
for file in v.files {
|
for file in v.files {
|
||||||
mut p := v.new_parser(file, RUN_MAIN)
|
mut p := v.new_parser(file, Pass.main)
|
||||||
p.parse()
|
p.parse()
|
||||||
// p.g.gen_x64()
|
// p.g.gen_x64()
|
||||||
// Format all files (don't format automatically generated vlib headers)
|
// Format all files (don't format automatically generated vlib headers)
|
||||||
@ -294,7 +290,7 @@ void init_consts();')
|
|||||||
}
|
}
|
||||||
v.log('Done parsing.')
|
v.log('Done parsing.')
|
||||||
// Write everything
|
// Write everything
|
||||||
mut d := strings.new_builder(10000)// Just to avoid some unnecessary allocations
|
mut d := strings.new_builder(10000)// Avoid unnecessary allocations
|
||||||
d.writeln(cgen.includes.join_lines())
|
d.writeln(cgen.includes.join_lines())
|
||||||
d.writeln(cgen.typedefs.join_lines())
|
d.writeln(cgen.typedefs.join_lines())
|
||||||
d.writeln(cgen.types.join_lines())
|
d.writeln(cgen.types.join_lines())
|
||||||
@ -524,7 +520,7 @@ fn (c &V) cc_windows_cross() {
|
|||||||
|
|
||||||
fn (v mut V) cc() {
|
fn (v mut V) cc() {
|
||||||
// Cross compiling for Windows
|
// Cross compiling for Windows
|
||||||
if v.os == WINDOWS {
|
if v.os == .windows {
|
||||||
$if !windows {
|
$if !windows {
|
||||||
v.cc_windows_cross()
|
v.cc_windows_cross()
|
||||||
return
|
return
|
||||||
@ -580,7 +576,7 @@ mut args := ''
|
|||||||
}
|
}
|
||||||
// Cross compiling linux
|
// Cross compiling linux
|
||||||
sysroot := '/Users/alex/tmp/lld/linuxroot/'
|
sysroot := '/Users/alex/tmp/lld/linuxroot/'
|
||||||
if v.os == LINUX && !linux_host {
|
if v.os == .linux && !linux_host {
|
||||||
// Build file.o
|
// Build file.o
|
||||||
a << '-c --sysroot=$sysroot -target x86_64-linux-gnu'
|
a << '-c --sysroot=$sysroot -target x86_64-linux-gnu'
|
||||||
// Right now `out_name` can be `file`, not `file.o`
|
// Right now `out_name` can be `file`, not `file.o`
|
||||||
@ -597,17 +593,17 @@ mut args := ''
|
|||||||
a << '"$TmpPath/$v.out_name_c"'
|
a << '"$TmpPath/$v.out_name_c"'
|
||||||
// }
|
// }
|
||||||
// Min macos version is mandatory I think?
|
// Min macos version is mandatory I think?
|
||||||
if v.os == MAC {
|
if v.os == .mac {
|
||||||
a << '-mmacosx-version-min=10.7'
|
a << '-mmacosx-version-min=10.7'
|
||||||
}
|
}
|
||||||
a << flags
|
a << flags
|
||||||
a << libs
|
a << libs
|
||||||
// macOS code can include objective C TODO remove once objective C is replaced with C
|
// macOS code can include objective C TODO remove once objective C is replaced with C
|
||||||
if v.os == MAC {
|
if v.os == .mac {
|
||||||
a << '-x objective-c'
|
a << '-x objective-c'
|
||||||
}
|
}
|
||||||
// Without these libs compilation will fail on Linux
|
// Without these libs compilation will fail on Linux
|
||||||
if v.os == LINUX && v.pref.build_mode != .build {
|
if v.os == .linux && v.pref.build_mode != .build {
|
||||||
a << '-lm -ldl -lpthread'
|
a << '-lm -ldl -lpthread'
|
||||||
}
|
}
|
||||||
// Find clang executable
|
// Find clang executable
|
||||||
@ -634,7 +630,7 @@ mut args := ''
|
|||||||
panic('clang error')
|
panic('clang error')
|
||||||
}
|
}
|
||||||
// Link it if we are cross compiling and need an executable
|
// Link it if we are cross compiling and need an executable
|
||||||
if v.os == LINUX && !linux_host && v.pref.build_mode != .build {
|
if v.os == .linux && !linux_host && v.pref.build_mode != .build {
|
||||||
v.out_name = v.out_name.replace('.o', '')
|
v.out_name = v.out_name.replace('.o', '')
|
||||||
obj_file := v.out_name + '.o'
|
obj_file := v.out_name + '.o'
|
||||||
println('linux obj_file=$obj_file out_name=$v.out_name')
|
println('linux obj_file=$obj_file out_name=$v.out_name')
|
||||||
@ -680,20 +676,20 @@ fn (v &V) v_files_from_dir(dir string) []string {
|
|||||||
if file.ends_with('_test.v') {
|
if file.ends_with('_test.v') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if file.ends_with('_win.v') && v.os != WINDOWS {
|
if file.ends_with('_win.v') && v.os != .windows {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if file.ends_with('_lin.v') && v.os != LINUX {
|
if file.ends_with('_lin.v') && v.os != .linux {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if file.ends_with('_mac.v') && v.os != MAC {
|
if file.ends_with('_mac.v') && v.os != .mac {
|
||||||
lin_file := file.replace('_mac.v', '_lin.v')
|
lin_file := file.replace('_mac.v', '_lin.v')
|
||||||
// println('lin_file="$lin_file"')
|
// println('lin_file="$lin_file"')
|
||||||
// If there are both _mav.v and _lin.v, don't use _mav.v
|
// If there are both _mav.v and _lin.v, don't use _mav.v
|
||||||
if os.file_exists('$dir/$lin_file') {
|
if os.file_exists('$dir/$lin_file') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
else if v.os == WINDOWS {
|
else if v.os == .windows {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -719,7 +715,7 @@ fn (v mut V) add_user_v_files() {
|
|||||||
if is_test_with_imports {
|
if is_test_with_imports {
|
||||||
user_files << dir
|
user_files << dir
|
||||||
pos := dir.last_index('/')
|
pos := dir.last_index('/')
|
||||||
dir = dir.left(pos) + '/'// TODO WHY IS THIS NEEDED?
|
dir = dir.left(pos) + '/'// TODO WHY IS THIS .neEDED?
|
||||||
}
|
}
|
||||||
if dir.ends_with('.v') {
|
if dir.ends_with('.v') {
|
||||||
// Just compile one file and get parent dir
|
// Just compile one file and get parent dir
|
||||||
@ -743,7 +739,7 @@ fn (v mut V) add_user_v_files() {
|
|||||||
}
|
}
|
||||||
// Parse user imports
|
// Parse user imports
|
||||||
for file in user_files {
|
for file in user_files {
|
||||||
mut p := v.new_parser(file, RUN_IMPORTS)
|
mut p := v.new_parser(file, Pass.imports)
|
||||||
p.parse()
|
p.parse()
|
||||||
}
|
}
|
||||||
// Parse lib imports
|
// Parse lib imports
|
||||||
@ -753,7 +749,7 @@ fn (v mut V) add_user_v_files() {
|
|||||||
vfiles := v.v_files_from_dir('$TmpPath/vlib/$pkg')
|
vfiles := v.v_files_from_dir('$TmpPath/vlib/$pkg')
|
||||||
// Add all imports referenced by these libs
|
// Add all imports referenced by these libs
|
||||||
for file in vfiles {
|
for file in vfiles {
|
||||||
mut p := v.new_parser(file, RUN_IMPORTS)
|
mut p := v.new_parser(file, Pass.imports)
|
||||||
p.parse()
|
p.parse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,7 +767,7 @@ fn (v mut V) add_user_v_files() {
|
|||||||
vfiles := v.v_files_from_dir(import_path)
|
vfiles := v.v_files_from_dir(import_path)
|
||||||
// Add all imports referenced by these libs
|
// Add all imports referenced by these libs
|
||||||
for file in vfiles {
|
for file in vfiles {
|
||||||
mut p := v.new_parser(file, RUN_IMPORTS)
|
mut p := v.new_parser(file, Pass.imports)
|
||||||
p.parse()
|
p.parse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -890,24 +886,24 @@ fn new_v(args[]string) *V {
|
|||||||
base := os.getwd().all_after('/')
|
base := os.getwd().all_after('/')
|
||||||
out_name = base.trim_space()
|
out_name = base.trim_space()
|
||||||
}
|
}
|
||||||
mut _os := MAC
|
mut _os := OS.mac
|
||||||
// No OS specifed? Use current system
|
// No OS specifed? Use current system
|
||||||
if target_os == '' {
|
if target_os == '' {
|
||||||
$if linux {
|
$if linux {
|
||||||
_os = LINUX
|
_os = .linux
|
||||||
}
|
}
|
||||||
$if mac {
|
$if mac {
|
||||||
_os = MAC
|
_os = .mac
|
||||||
}
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
_os = WINDOWS
|
_os = .windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch target_os {
|
switch target_os {
|
||||||
case 'linux': _os = LINUX
|
case 'linux': _os = .linux
|
||||||
case 'windows': _os = WINDOWS
|
case 'windows': _os = .windows
|
||||||
case 'mac': _os = MAC
|
case 'mac': _os = .mac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builtins := [
|
builtins := [
|
||||||
@ -960,7 +956,7 @@ fn new_v(args[]string) *V {
|
|||||||
mut f := '$lang_dir/vlib/builtin/$builtin'
|
mut f := '$lang_dir/vlib/builtin/$builtin'
|
||||||
// In default mode we use precompiled vlib.o, point to .vh files with signatures
|
// In default mode we use precompiled vlib.o, point to .vh files with signatures
|
||||||
if build_mode == .default_mode || build_mode == .build {
|
if build_mode == .default_mode || build_mode == .build {
|
||||||
f = '$TmpPath/vlib/builtin/${builtin}h'
|
//f = '$TmpPath/vlib/builtin/${builtin}h'
|
||||||
}
|
}
|
||||||
files << f
|
files << f
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -148,7 +148,7 @@ fn (s mut Scanner) skip_whitespace() {
|
|||||||
s.pos++
|
s.pos++
|
||||||
}
|
}
|
||||||
// if s.pos == s.text.len {
|
// if s.pos == s.text.len {
|
||||||
// return scan_res(EOF, '')
|
// return scan_res(.eof, '')
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,14 +175,14 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
}
|
}
|
||||||
s.started = true
|
s.started = true
|
||||||
if s.pos >= s.text.len {
|
if s.pos >= s.text.len {
|
||||||
return scan_res(EOF, '')
|
return scan_res(.eof, '')
|
||||||
}
|
}
|
||||||
// skip whitespace
|
// skip whitespace
|
||||||
if !s.inside_string {
|
if !s.inside_string {
|
||||||
s.skip_whitespace()
|
s.skip_whitespace()
|
||||||
}
|
}
|
||||||
if s.is_fmt && s.text[s.pos] == `\n` {
|
if s.is_fmt && s.text[s.pos] == `\n` {
|
||||||
return scan_res(NL, '')
|
return scan_res(.nl, '')
|
||||||
}
|
}
|
||||||
// End of $var, start next string
|
// End of $var, start next string
|
||||||
if !s.is_fmt && s.dollar_end {
|
if !s.is_fmt && s.dollar_end {
|
||||||
@ -190,16 +190,16 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
if s.text[s.pos] == SINGLE_QUOTE {
|
if s.text[s.pos] == SINGLE_QUOTE {
|
||||||
// fmt.Println("ENDDD")
|
// fmt.Println("ENDDD")
|
||||||
s.dollar_end = false
|
s.dollar_end = false
|
||||||
return scan_res(STRING, '')
|
return scan_res(.strtoken, '')
|
||||||
}
|
}
|
||||||
s.dollar_end = false
|
s.dollar_end = false
|
||||||
return scan_res(STRING, s.ident_string())
|
return scan_res(.strtoken, s.ident_string())
|
||||||
}
|
}
|
||||||
s.skip_whitespace()
|
s.skip_whitespace()
|
||||||
// end of file
|
// end of file
|
||||||
if s.pos >= s.text.len {
|
if s.pos >= s.text.len {
|
||||||
// println('scan(): returning EOF (pos >= len)')
|
// println('scan(): returning .eof (pos >= len)')
|
||||||
return scan_res(EOF, '')
|
return scan_res(.eof, '')
|
||||||
}
|
}
|
||||||
// handle each char
|
// handle each char
|
||||||
c := s.text[s.pos]
|
c := s.text[s.pos]
|
||||||
@ -211,7 +211,7 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
if is_name_char(c) {
|
if is_name_char(c) {
|
||||||
name := s.ident_name()
|
name := s.ident_name()
|
||||||
// tmp hack to detect . in ${}
|
// tmp hack to detect . in ${}
|
||||||
// Check if not EOF to prevent panic
|
// Check if not .eof to prevent panic
|
||||||
next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` }
|
next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` }
|
||||||
// println('!!! got name=$name next_char=$next_char')
|
// println('!!! got name=$name next_char=$next_char')
|
||||||
if is_key(name) {
|
if is_key(name) {
|
||||||
@ -232,7 +232,7 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.dollar_start && next_char != `.` {
|
if s.dollar_start && next_char != `.` {
|
||||||
// println('INSIDE STRING .dollar var=$name')
|
// println('INSIDE .strtoken .dollar var=$name')
|
||||||
s.dollar_end = true
|
s.dollar_end = true
|
||||||
s.dollar_start = false
|
s.dollar_start = false
|
||||||
}
|
}
|
||||||
@ -241,128 +241,128 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
//If a single letter name at the start of the file, increment
|
//If a single letter name at the start of the file, increment
|
||||||
//Otherwise the scanner would be stuck at s.pos = 0
|
//Otherwise the scanner would be stuck at s.pos = 0
|
||||||
}
|
}
|
||||||
return scan_res(NAME, name)
|
return scan_res(.name, name)
|
||||||
}
|
}
|
||||||
// number, `.123`
|
// number, `.123`
|
||||||
else if c.is_digit() || c == `.` && nextc.is_digit() {
|
else if c.is_digit() || c == `.` && nextc.is_digit() {
|
||||||
num := s.ident_number()
|
num := s.ident_number()
|
||||||
return scan_res(INT, num)
|
return scan_res(.integer, num)
|
||||||
}
|
}
|
||||||
// all other tokens
|
// all other tokens
|
||||||
switch c {
|
switch c {
|
||||||
case `+`:
|
case `+`:
|
||||||
if nextc == `+` {
|
if nextc == `+` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(INC, '')
|
return scan_res(.inc, '')
|
||||||
}
|
}
|
||||||
else if nextc == `=` {
|
else if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(PLUS_ASSIGN, '')
|
return scan_res(.plus_assign, '')
|
||||||
}
|
}
|
||||||
return scan_res(PLUS, '')
|
return scan_res(.plus, '')
|
||||||
case `-`:
|
case `-`:
|
||||||
if nextc == `-` {
|
if nextc == `-` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(DEC, '')
|
return scan_res(.dec, '')
|
||||||
}
|
}
|
||||||
else if nextc == `=` {
|
else if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(MINUS_ASSIGN, '')
|
return scan_res(.minus_assign, '')
|
||||||
}
|
}
|
||||||
return scan_res(MINUS, '')
|
return scan_res(.minus, '')
|
||||||
case `*`:
|
case `*`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(MULT_ASSIGN, '')
|
return scan_res(.mult_assign, '')
|
||||||
}
|
}
|
||||||
return scan_res(MUL, '')
|
return scan_res(.mul, '')
|
||||||
case `^`:
|
case `^`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(XOR_ASSIGN, '')
|
return scan_res(.xor_assign, '')
|
||||||
}
|
}
|
||||||
return scan_res(XOR, '')
|
return scan_res(.xor, '')
|
||||||
case `%`:
|
case `%`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(MOD_ASSIGN, '')
|
return scan_res(.mod_assign, '')
|
||||||
}
|
}
|
||||||
return scan_res(MOD, '')
|
return scan_res(.mod, '')
|
||||||
case `?`:
|
case `?`:
|
||||||
return scan_res(QUESTION, '')
|
return scan_res(.question, '')
|
||||||
case SINGLE_QUOTE:
|
case SINGLE_QUOTE:
|
||||||
return scan_res(STRING, s.ident_string())
|
return scan_res(.strtoken, s.ident_string())
|
||||||
// TODO allow double quotes
|
// TODO allow double quotes
|
||||||
// case QUOTE:
|
// case QUOTE:
|
||||||
// return scan_res(STRING, s.ident_string())
|
// return scan_res(.strtoken, s.ident_string())
|
||||||
case `\``:
|
case `\``:
|
||||||
return scan_res(CHAR, s.ident_char())
|
return scan_res(.chartoken, s.ident_char())
|
||||||
case `(`:
|
case `(`:
|
||||||
return scan_res(LPAR, '')
|
return scan_res(.lpar, '')
|
||||||
case `)`:
|
case `)`:
|
||||||
return scan_res(RPAR, '')
|
return scan_res(.rpar, '')
|
||||||
case `[`:
|
case `[`:
|
||||||
return scan_res(LSBR, '')
|
return scan_res(.lsbr, '')
|
||||||
case `]`:
|
case `]`:
|
||||||
return scan_res(RSBR, '')
|
return scan_res(.rsbr, '')
|
||||||
case `{`:
|
case `{`:
|
||||||
// Skip { in ${ in strings
|
// Skip { in ${ in strings
|
||||||
if s.inside_string {
|
if s.inside_string {
|
||||||
return s.scan()
|
return s.scan()
|
||||||
}
|
}
|
||||||
return scan_res(LCBR, '')
|
return scan_res(.lcbr, '')
|
||||||
case `$`:
|
case `$`:
|
||||||
return scan_res(DOLLAR, '')
|
return scan_res(.dollar, '')
|
||||||
case `}`:
|
case `}`:
|
||||||
// s = `hello $name kek`
|
// s = `hello $name kek`
|
||||||
// s = `hello ${name} kek`
|
// s = `hello ${name} kek`
|
||||||
if s.inside_string {
|
if s.inside_string {
|
||||||
s.pos++
|
s.pos++
|
||||||
// TODO UNNEEDED?
|
// TODO UN.neEDED?
|
||||||
if s.text[s.pos] == SINGLE_QUOTE {
|
if s.text[s.pos] == SINGLE_QUOTE {
|
||||||
s.inside_string = false
|
s.inside_string = false
|
||||||
return scan_res(STRING, '')
|
return scan_res(.strtoken, '')
|
||||||
}
|
}
|
||||||
return scan_res(STRING, s.ident_string())
|
return scan_res(.strtoken, s.ident_string())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(RCBR, '')
|
return scan_res(.rcbr, '')
|
||||||
}
|
}
|
||||||
case `&`:
|
case `&`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(AND_ASSIGN, '')
|
return scan_res(.and_assign, '')
|
||||||
}
|
}
|
||||||
if nextc == `&` {
|
if nextc == `&` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(AND, '')
|
return scan_res(.and, '')
|
||||||
}
|
}
|
||||||
return scan_res(AMP, '')
|
return scan_res(.amp, '')
|
||||||
case `|`:
|
case `|`:
|
||||||
if nextc == `|` {
|
if nextc == `|` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(OR, '')
|
return scan_res(.ortok, '')
|
||||||
}
|
}
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(OR_ASSIGN, '')
|
return scan_res(.or_assign, '')
|
||||||
}
|
}
|
||||||
return scan_res(PIPE, '')
|
return scan_res(.pipe, '')
|
||||||
case `,`:
|
case `,`:
|
||||||
return scan_res(COMMA, '')
|
return scan_res(.comma, '')
|
||||||
case `\r`:
|
case `\r`:
|
||||||
if nextc == `\n` {
|
if nextc == `\n` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(NL, '')
|
return scan_res(.nl, '')
|
||||||
}
|
}
|
||||||
case `\n`:
|
case `\n`:
|
||||||
return scan_res(NL, '')
|
return scan_res(.nl, '')
|
||||||
case `.`:
|
case `.`:
|
||||||
if nextc == `.` {
|
if nextc == `.` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(DOTDOT, '')
|
return scan_res(.dotdot, '')
|
||||||
}
|
}
|
||||||
return scan_res(DOT, '')
|
return scan_res(.dot, '')
|
||||||
case `#`:
|
case `#`:
|
||||||
start := s.pos + 1
|
start := s.pos + 1
|
||||||
for s.pos < s.text.len && s.text[s.pos] != `\n` {
|
for s.pos < s.text.len && s.text[s.pos] != `\n` {
|
||||||
@ -374,74 +374,74 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
// fmt needs NL after #
|
// fmt needs NL after #
|
||||||
s.pos--
|
s.pos--
|
||||||
}
|
}
|
||||||
return scan_res(HASH, hash.trim_space())
|
return scan_res(.hash, hash.trim_space())
|
||||||
case `>`:
|
case `>`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(GE, '')
|
return scan_res(.ge, '')
|
||||||
}
|
}
|
||||||
else if nextc == `>` {
|
else if nextc == `>` {
|
||||||
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return scan_res(RIGHT_SHIFT_ASSIGN, '')
|
return scan_res(.righ_shift_assign, '')
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(RIGHT_SHIFT, '')
|
return scan_res(.righ_shift, '')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(GT, '')
|
return scan_res(.gt, '')
|
||||||
}
|
}
|
||||||
case `<`:
|
case `<`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(LE, '')
|
return scan_res(.le, '')
|
||||||
}
|
}
|
||||||
else if nextc == `<` {
|
else if nextc == `<` {
|
||||||
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return scan_res(LEFT_SHIFT_ASSIGN, '')
|
return scan_res(.left_shift_assign, '')
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(LEFT_SHIFT, '')
|
return scan_res(.left_shift, '')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(LT, '')
|
return scan_res(.lt, '')
|
||||||
}
|
}
|
||||||
case `=`:
|
case `=`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(EQ, '')
|
return scan_res(.eq, '')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(ASSIGN, '')
|
return scan_res(.assign, '')
|
||||||
}
|
}
|
||||||
case `:`:
|
case `:`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(DECL_ASSIGN, '')
|
return scan_res(.decl_assign, '')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(COLON, '')
|
return scan_res(.colon, '')
|
||||||
}
|
}
|
||||||
case `;`:
|
case `;`:
|
||||||
return scan_res(SEMICOLON, '')
|
return scan_res(.semicolon, '')
|
||||||
case `!`:
|
case `!`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(NE, '')
|
return scan_res(.ne, '')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(NOT, '')
|
return scan_res(.not, '')
|
||||||
}
|
}
|
||||||
case `~`:
|
case `~`:
|
||||||
return scan_res(BIT_NOT, '')
|
return scan_res(.bit_not, '')
|
||||||
case `/`:
|
case `/`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(DIV_ASSIGN, '')
|
return scan_res(.div_assign, '')
|
||||||
}
|
}
|
||||||
if nextc == `/` {
|
if nextc == `/` {
|
||||||
// debug("!!!!!!GOT LINE COM")
|
// debug("!!!!!!.key_goT LI.ne COM")
|
||||||
start := s.pos + 1
|
start := s.pos + 1
|
||||||
for s.pos < s.text.len && s.text[s.pos] != `\n`{
|
for s.pos < s.text.len && s.text[s.pos] != `\n`{
|
||||||
s.pos++
|
s.pos++
|
||||||
@ -458,7 +458,7 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
// Skip comment
|
// Skip comment
|
||||||
return s.scan()
|
return s.scan()
|
||||||
}
|
}
|
||||||
return scan_res(LINE_COM, s.line_comment)
|
return scan_res(.line_com, s.line_comment)
|
||||||
}
|
}
|
||||||
// Multiline comments
|
// Multiline comments
|
||||||
if nextc == `*` {
|
if nextc == `*` {
|
||||||
@ -488,16 +488,16 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
comm := s.text.substr(start, end)
|
comm := s.text.substr(start, end)
|
||||||
s.fgenln(comm)
|
s.fgenln(comm)
|
||||||
if s.is_fmt {
|
if s.is_fmt {
|
||||||
return scan_res(MLINE_COM, comm)
|
return scan_res(.mline_com, comm)
|
||||||
}
|
}
|
||||||
// Skip if not in fmt mode
|
// Skip if not in fmt mode
|
||||||
return s.scan()
|
return s.scan()
|
||||||
}
|
}
|
||||||
return scan_res(DIV, '')
|
return scan_res(.div, '')
|
||||||
}
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
if c == `\0` {
|
if c == `\0` {
|
||||||
return scan_res(EOF, '')
|
return scan_res(.eof, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println('(char code=$c) pos=$s.pos len=$s.text.len')
|
println('(char code=$c) pos=$s.pos len=$s.text.len')
|
||||||
@ -506,7 +506,7 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
msg += ', use \' to denote strings'
|
msg += ', use \' to denote strings'
|
||||||
}
|
}
|
||||||
s.error(msg)
|
s.error(msg)
|
||||||
return scan_res(EOF, '')
|
return scan_res(.eof, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s &Scanner) error(msg string) {
|
fn (s &Scanner) error(msg string) {
|
||||||
@ -637,7 +637,7 @@ fn (s mut Scanner) ident_char() string {
|
|||||||
fn (p mut Parser) peek() Token {
|
fn (p mut Parser) peek() Token {
|
||||||
for {
|
for {
|
||||||
tok := p.scanner.peek()
|
tok := p.scanner.peek()
|
||||||
if tok != NL {
|
if tok != .nl {
|
||||||
return tok
|
return tok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -681,7 +681,7 @@ fn (s mut Scanner) debug_tokens() {
|
|||||||
println('')
|
println('')
|
||||||
}
|
}
|
||||||
// allToks += "\n"
|
// allToks += "\n"
|
||||||
if tok == EOF {
|
if tok == .eof {
|
||||||
println('============ END OF DEBUG TOKENS ==================')
|
println('============ END OF DEBUG TOKENS ==================')
|
||||||
// fmt.Println("========"+s.file+"========\n", allToks)
|
// fmt.Println("========"+s.file+"========\n", allToks)
|
||||||
break
|
break
|
||||||
|
@ -18,24 +18,25 @@ mut:
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum AccessMod {
|
enum AccessMod {
|
||||||
PRIVATE // private immutable
|
private // private imkey_mut
|
||||||
PRIVET_MUT // private mutable
|
private_mut // private key_mut
|
||||||
PUBLIC // public immmutable (readonly)
|
public // public immkey_mut (readonly)
|
||||||
PUBLIC_MUT // public, but mutable only in this module
|
public_mut // public, but key_mut 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)
|
public_mut_mut // public and key_mut both inside and outside (not recommended to use, that's why it's so verbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
mut:
|
mut:
|
||||||
pkg string
|
mod string
|
||||||
name string
|
name string
|
||||||
fields []Var
|
fields []Var
|
||||||
methods []Fn
|
methods []Fn
|
||||||
parent string
|
parent string
|
||||||
func Fn // For cat == FN (type kek fn())
|
func Fn // For cat == FN (type kek fn())
|
||||||
is_c bool // C.FILE
|
is_c bool // C.FI.le
|
||||||
is_interface bool
|
is_interface bool
|
||||||
is_enum bool
|
is_enum bool
|
||||||
|
enum_vals []string
|
||||||
// This field is used for types that are not defined yet but are known to exist.
|
// 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.
|
// It allows having things like `fn (f Foo) bar()` before `Foo` is defined.
|
||||||
// This information is needed in the first pass.
|
// This information is needed in the first pass.
|
||||||
@ -117,8 +118,7 @@ fn new_table(obfuscate bool) *Table {
|
|||||||
t.register_type_with_parent('i32', 'int')
|
t.register_type_with_parent('i32', 'int')
|
||||||
t.register_type_with_parent('u32', 'int')
|
t.register_type_with_parent('u32', 'int')
|
||||||
t.register_type_with_parent('byte', 'int')
|
t.register_type_with_parent('byte', 'int')
|
||||||
// t.register_type_with_parent('i64', 'int')
|
t.register_type_with_parent('i64', 'int')
|
||||||
t.register_type('i64')
|
|
||||||
t.register_type_with_parent('u64', 'int')
|
t.register_type_with_parent('u64', 'int')
|
||||||
t.register_type('byteptr')
|
t.register_type('byteptr')
|
||||||
t.register_type('intptr')
|
t.register_type('intptr')
|
||||||
@ -159,13 +159,13 @@ fn (table &Table) known_pkg(pkg string) bool {
|
|||||||
return pkg in table.packages
|
return pkg in table.packages
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (t mut Table) register_const(name, typ, pkg string, is_imported bool) {
|
fn (t mut Table) register_const(name, typ, mod string, is_imported bool) {
|
||||||
t.consts << Var {
|
t.consts << Var {
|
||||||
name: name
|
name: name
|
||||||
typ: typ
|
typ: typ
|
||||||
is_const: true
|
is_const: true
|
||||||
is_import_const: is_imported
|
is_import_const: is_imported
|
||||||
pkg: pkg
|
mod: mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ fn (p mut Parser) register_global(name, typ string) {
|
|||||||
typ: typ
|
typ: typ
|
||||||
is_const: true
|
is_const: true
|
||||||
is_global: true
|
is_global: true
|
||||||
pkg: p.pkg
|
mod: p.mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ fn (p mut Parser) register_type_with_parent(strtyp, parent string) {
|
|||||||
typ := Type {
|
typ := Type {
|
||||||
name: strtyp
|
name: strtyp
|
||||||
parent: parent
|
parent: parent
|
||||||
pkg: p.pkg
|
mod: p.mod
|
||||||
}
|
}
|
||||||
p.table.register_type2(typ)
|
p.table.register_type2(typ)
|
||||||
}
|
}
|
||||||
@ -297,6 +297,10 @@ fn (t &Type) has_field(name string) bool {
|
|||||||
return (field.name != '')
|
return (field.name != '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (t &Type) has_enum_val(name string) bool {
|
||||||
|
return name in t.enum_vals
|
||||||
|
}
|
||||||
|
|
||||||
fn (t &Type) find_field(name string) Var {
|
fn (t &Type) find_field(name string) Var {
|
||||||
for field in t.fields {
|
for field in t.fields {
|
||||||
if field.name == name {
|
if field.name == name {
|
||||||
|
388
compiler/token.v
388
compiler/token.v
@ -5,214 +5,212 @@
|
|||||||
module main
|
module main
|
||||||
|
|
||||||
enum Token {
|
enum Token {
|
||||||
EOF
|
eof
|
||||||
NAME
|
name
|
||||||
INT
|
integer
|
||||||
STRING
|
strtoken
|
||||||
CHAR
|
chartoken
|
||||||
PLUS
|
plus
|
||||||
MINUS
|
minus
|
||||||
MUL
|
mul
|
||||||
DIV
|
div
|
||||||
MOD
|
mod
|
||||||
XOR
|
xor
|
||||||
PIPE
|
pipe
|
||||||
INC
|
inc
|
||||||
DEC
|
dec
|
||||||
AND
|
and
|
||||||
OR
|
ortok
|
||||||
NOT
|
not
|
||||||
BIT_NOT
|
bit_not
|
||||||
QUESTION
|
question
|
||||||
COMMA
|
comma
|
||||||
SEMICOLON
|
semicolon
|
||||||
COLON
|
colon
|
||||||
AMP
|
amp
|
||||||
HASH
|
hash
|
||||||
DOLLAR
|
dollar
|
||||||
LEFT_SHIFT
|
left_shift
|
||||||
RIGHT_SHIFT
|
righ_shift
|
||||||
// = := += -=
|
// = := += -=
|
||||||
ASSIGN
|
assign
|
||||||
DECL_ASSIGN
|
decl_assign
|
||||||
PLUS_ASSIGN
|
plus_assign
|
||||||
MINUS_ASSIGN
|
minus_assign
|
||||||
DIV_ASSIGN
|
div_assign
|
||||||
MULT_ASSIGN
|
mult_assign
|
||||||
XOR_ASSIGN
|
xor_assign
|
||||||
MOD_ASSIGN
|
mod_assign
|
||||||
OR_ASSIGN
|
or_assign
|
||||||
AND_ASSIGN
|
and_assign
|
||||||
RIGHT_SHIFT_ASSIGN
|
righ_shift_assign
|
||||||
LEFT_SHIFT_ASSIGN
|
left_shift_assign
|
||||||
// {} () []
|
// {} () []
|
||||||
LCBR
|
lcbr
|
||||||
RCBR
|
rcbr
|
||||||
LPAR
|
lpar
|
||||||
RPAR
|
rpar
|
||||||
LSBR
|
lsbr
|
||||||
RSBR
|
rsbr
|
||||||
// == != <= < >= >
|
// == != <= < >= >
|
||||||
EQ
|
eq
|
||||||
NE
|
ne
|
||||||
GT
|
gt
|
||||||
LT
|
lt
|
||||||
GE
|
ge
|
||||||
LE
|
le
|
||||||
// comments
|
// comments
|
||||||
LINE_COM
|
line_com
|
||||||
MLINE_COM
|
mline_com
|
||||||
NL
|
nl
|
||||||
DOT
|
dot
|
||||||
DOTDOT
|
dotdot
|
||||||
// keywords
|
// keywords
|
||||||
keyword_beg
|
keyword_beg
|
||||||
PACKAGE
|
key_module
|
||||||
// MODULE
|
key_struct
|
||||||
STRUCT
|
key_if
|
||||||
IF
|
key_else
|
||||||
ELSE
|
key_return
|
||||||
RETURN
|
key_go
|
||||||
GO
|
key_const
|
||||||
CONST
|
key_import_const
|
||||||
IMPORT_CONST
|
key_mut
|
||||||
MUT
|
typ
|
||||||
TIP
|
key_enum
|
||||||
ENUM
|
key_for
|
||||||
FOR
|
key_switch
|
||||||
SWITCH
|
|
||||||
MATCH
|
MATCH
|
||||||
CASE
|
key_case
|
||||||
FUNC
|
func
|
||||||
TRUE
|
key_true
|
||||||
FALSE
|
key_false
|
||||||
CONTINUE
|
key_continue
|
||||||
BREAK
|
key_break
|
||||||
EMBED
|
key_embed
|
||||||
IMPORT
|
key_import
|
||||||
TYPEOF
|
//typeof
|
||||||
DEFAULT
|
key_default
|
||||||
ENDIF
|
key_assert
|
||||||
ASSERT
|
key_sizeof
|
||||||
SIZEOF
|
key_in
|
||||||
IN
|
key_atomic
|
||||||
ATOMIC
|
key_interface
|
||||||
INTERFACE
|
key_orelse
|
||||||
OR_ELSE
|
key_global
|
||||||
GLOBAL
|
key_union
|
||||||
UNION
|
key_pub
|
||||||
PUB
|
key_goto
|
||||||
GOTO
|
key_static
|
||||||
STATIC
|
|
||||||
keyword_end
|
keyword_end
|
||||||
}
|
}
|
||||||
|
|
||||||
// build_keys genereates a map with keywords' string values:
|
// build_keys genereates a map with keywords' string values:
|
||||||
// Keywords['return'] == .return
|
// Keywords['return'] == .key_return
|
||||||
fn build_keys() map_int {
|
fn build_keys() map_int {
|
||||||
mut res := map[string]int{}
|
mut res := map[string]int{}
|
||||||
for t := int(keyword_beg) + 1; t < int(keyword_end); t++ {
|
for t := int(Token.keyword_beg) + 1; t < int(Token.keyword_end); t++ {
|
||||||
key := TOKENSTR[t]
|
key := TOKENSTR[t]
|
||||||
res[key] = int(t)
|
res[key] = int(t)
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO remove once we have `enum Token { name('name') if('if') ... }`
|
||||||
fn build_token_str() []string {
|
fn build_token_str() []string {
|
||||||
mut s := [''; NrTokens]
|
mut s := [''; NrTokens]
|
||||||
s[keyword_beg] = ''
|
s[Token.keyword_beg] = ''
|
||||||
s[keyword_end] = ''
|
s[Token.keyword_end] = ''
|
||||||
s[EOF] = 'EOF'
|
s[Token.eof] = '.eof'
|
||||||
s[NAME] = 'NAME'
|
s[Token.name] = '.name'
|
||||||
s[INT] = 'INT'
|
s[Token.integer] = '.integer'
|
||||||
s[STRING] = 'STR'
|
s[Token.strtoken] = 'STR'
|
||||||
s[CHAR] = 'CHAR'
|
s[Token.chartoken] = '.chartoken'
|
||||||
s[PLUS] = '+'
|
s[Token.plus] = '+'
|
||||||
s[MINUS] = '-'
|
s[Token.minus] = '-'
|
||||||
s[MUL] = '*'
|
s[Token.mul] = '*'
|
||||||
s[DIV] = '/'
|
s[Token.div] = '/'
|
||||||
s[MOD] = '%'
|
s[Token.mod] = '%'
|
||||||
s[XOR] = '^'
|
s[Token.xor] = '^'
|
||||||
s[BIT_NOT] = '~'
|
s[Token.bit_not] = '~'
|
||||||
s[PIPE] = '|'
|
s[Token.pipe] = '|'
|
||||||
s[HASH] = '#'
|
s[Token.hash] = '#'
|
||||||
s[AMP] = '&'
|
s[Token.amp] = '&'
|
||||||
s[INC] = '++'
|
s[Token.inc] = '++'
|
||||||
s[DEC] = '--'
|
s[Token.dec] = '--'
|
||||||
s[AND] = '&&'
|
s[Token.and] = '&&'
|
||||||
s[OR] = '||'
|
s[Token.ortok] = '||'
|
||||||
s[NOT] = '!'
|
s[Token.not] = '!'
|
||||||
s[DOT] = '.'
|
s[Token.dot] = '.'
|
||||||
s[DOTDOT] = '..'
|
s[Token.dotdot] = '..'
|
||||||
s[COMMA] = ','
|
s[Token.comma] = ','
|
||||||
s[SEMICOLON] = ';'
|
s[Token.semicolon] = ';'
|
||||||
s[COLON] = ':'
|
s[Token.colon] = ':'
|
||||||
s[ASSIGN] = '='
|
s[Token.assign] = '='
|
||||||
s[DECL_ASSIGN] = ':='
|
s[Token.decl_assign] = ':='
|
||||||
s[PLUS_ASSIGN] = '+='
|
s[Token.plus_assign] = '+='
|
||||||
s[MINUS_ASSIGN] = '-='
|
s[Token.minus_assign] = '-='
|
||||||
s[MULT_ASSIGN] = '*='
|
s[Token.mult_assign] = '*='
|
||||||
s[DIV_ASSIGN] = '/='
|
s[Token.div_assign] = '/='
|
||||||
s[XOR_ASSIGN] = '^='
|
s[Token.xor_assign] = '^='
|
||||||
s[MOD_ASSIGN] = '%='
|
s[Token.mod_assign] = '%='
|
||||||
s[OR_ASSIGN] = '|='
|
s[Token.or_assign] = '|='
|
||||||
s[AND_ASSIGN] = '&='
|
s[Token.and_assign] = '&='
|
||||||
s[RIGHT_SHIFT_ASSIGN] = '>>='
|
s[Token.righ_shift_assign] = '>>='
|
||||||
s[LEFT_SHIFT_ASSIGN] = '<<='
|
s[Token.left_shift_assign] = '<<='
|
||||||
s[LCBR] = '{'
|
s[Token.lcbr] = '{'
|
||||||
s[RCBR] = '}'
|
s[Token.rcbr] = '}'
|
||||||
s[LPAR] = '('
|
s[Token.lpar] = '('
|
||||||
s[RPAR] = ')'
|
s[Token.rpar] = ')'
|
||||||
s[LSBR] = '['
|
s[Token.lsbr] = '['
|
||||||
s[RSBR] = ']'
|
s[Token.rsbr] = ']'
|
||||||
s[EQ] = '=='
|
s[Token.eq] = '=='
|
||||||
s[NE] = '!='
|
s[Token.ne] = '!='
|
||||||
s[GT] = '>'
|
s[Token.gt] = '>'
|
||||||
s[LT] = '<'
|
s[Token.lt] = '<'
|
||||||
s[GE] = '>='
|
s[Token.ge] = '>='
|
||||||
s[LE] = '<='
|
s[Token.le] = '<='
|
||||||
s[QUESTION] = '?'
|
s[Token.question] = '?'
|
||||||
s[LEFT_SHIFT] = '<<'
|
s[Token.left_shift] = '<<'
|
||||||
s[RIGHT_SHIFT] = '>>'
|
s[Token.righ_shift] = '>>'
|
||||||
s[LINE_COM] = '//'
|
s[Token.line_com] = '//'
|
||||||
s[NL] = 'NLL'
|
s[Token.nl] = 'NLL'
|
||||||
s[DOLLAR] = '$'
|
s[Token.dollar] = '$'
|
||||||
s[ASSERT] = 'assert'
|
s[Token.key_assert] = 'assert'
|
||||||
s[STRUCT] = 'struct'
|
s[Token.key_struct] = 'struct'
|
||||||
s[IF] = 'if'
|
s[Token.key_if] = 'if'
|
||||||
s[ELSE] = 'else'
|
s[Token.key_else] = 'else'
|
||||||
s[RETURN] = 'return'
|
s[Token.key_return] = 'return'
|
||||||
s[PACKAGE] = 'module'
|
s[Token.key_module] = 'module'
|
||||||
s[SIZEOF] = 'sizeof'
|
s[Token.key_sizeof] = 'sizeof'
|
||||||
s[GO] = 'go'
|
s[Token.key_go] = 'go'
|
||||||
s[GOTO] = 'goto'
|
s[Token.key_goto] = 'goto'
|
||||||
s[CONST] = 'const'
|
s[Token.key_const] = 'const'
|
||||||
s[MUT] = 'mut'
|
s[Token.key_mut] = 'mut'
|
||||||
s[TIP] = 'type'
|
s[Token.typ] = 'type'
|
||||||
s[FOR] = 'for'
|
s[Token.key_for] = 'for'
|
||||||
s[SWITCH] = 'switch'
|
s[Token.key_switch] = 'switch'
|
||||||
s[MATCH] = 'match'
|
//Tokens[MATCH] = 'match'
|
||||||
s[CASE] = 'case'
|
s[Token.key_case] = 'case'
|
||||||
s[FUNC] = 'fn'
|
s[Token.func] = 'fn'
|
||||||
s[TRUE] = 'true'
|
s[Token.key_true] = 'true'
|
||||||
s[FALSE] = 'false'
|
s[Token.key_false] = 'false'
|
||||||
s[CONTINUE] = 'continue'
|
s[Token.key_continue] = 'continue'
|
||||||
s[BREAK] = 'break'
|
s[Token.key_break] = 'break'
|
||||||
s[IMPORT] = 'import'
|
s[Token.key_import] = 'import'
|
||||||
s[EMBED] = 'embed'
|
s[Token.key_embed] = 'embed'
|
||||||
s[TYPEOF] = 'typeof'
|
//Tokens[TYP.eof] = 'typeof'
|
||||||
s[DEFAULT] = 'default'
|
s[Token.key_default] = 'default'
|
||||||
s[ENDIF] = 'endif'
|
s[Token.key_enum] = 'enum'
|
||||||
s[ENUM] = 'enum'
|
s[Token.key_interface] = 'interface'
|
||||||
s[INTERFACE] = 'interface'
|
s[Token.key_pub] = 'pub'
|
||||||
s[PUB] = 'pub'
|
s[Token.key_import_const] = 'import_const'
|
||||||
s[IMPORT_CONST] = 'import_const'
|
s[Token.key_in] = 'in'
|
||||||
s[IN] = 'in'
|
s[Token.key_atomic] = 'atomic'
|
||||||
s[ATOMIC] = 'atomic'
|
s[Token.key_orelse] = 'or'
|
||||||
s[OR_ELSE] = 'or'
|
s[Token.key_global] = '__global'
|
||||||
s[GLOBAL] = '__global'
|
s[Token.key_union] = 'union'
|
||||||
s[UNION] = 'union'
|
s[Token.key_static] = 'static'
|
||||||
s[STATIC] = 'static'
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,17 +234,19 @@ fn (t Token) str() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (t Token) is_decl() bool {
|
fn (t Token) is_decl() bool {
|
||||||
// TODO return t in [FUNC ,TIP, CONST, IMPORT_CONST ,AT ,EOF]
|
// TODO return t in [.func ,.typ, .key_const, .key_import_.key_const ,AT ,.eof]
|
||||||
return t == ENUM || t == INTERFACE || t == FUNC || t == STRUCT || t == TIP ||
|
return t == .key_enum || t == .key_interface || t == .func ||
|
||||||
t == CONST || t == IMPORT_CONST || t == PUB || t == EOF
|
t == .key_struct || t == .typ ||
|
||||||
|
t == .key_const || t == .key_import_const || t == .key_pub || t == .eof
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AssignTokens = [
|
AssignTokens = [
|
||||||
ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN,
|
Token.assign, Token.plus_assign, Token.minus_assign,
|
||||||
MULT_ASSIGN, DIV_ASSIGN, XOR_ASSIGN, MOD_ASSIGN,
|
Token.mult_assign, Token.div_assign, Token.xor_assign,
|
||||||
OR_ASSIGN, AND_ASSIGN, RIGHT_SHIFT_ASSIGN,
|
Token.mod_assign,
|
||||||
LEFT_SHIFT_ASSIGN
|
Token.or_assign, Token.and_assign, Token.righ_shift_assign,
|
||||||
|
Token.left_shift_assign
|
||||||
]
|
]
|
||||||
|
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user