mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
enums (mode == .default_mode
syntax); fix foo.bar[0].baz = val
This commit is contained in:
parent
859c8ffdb8
commit
a9b8bc067f
@ -95,7 +95,7 @@ fn (f mut Fn) clear_vars() {
|
|||||||
|
|
||||||
// vlib header file?
|
// vlib header file?
|
||||||
fn (p mut Parser) is_sig() bool {
|
fn (p mut Parser) is_sig() bool {
|
||||||
return (p.pref.build_mode == default_mode || p.pref.build_mode == build) &&
|
return (p.pref.build_mode == .default_mode || p.pref.build_mode == .build) &&
|
||||||
(p.file_path.contains(TmpPath))
|
(p.file_path.contains(TmpPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
// Add function definition to the top
|
// Add function definition to the top
|
||||||
if !is_c && f.name != 'main' && p.first_run() {
|
if !is_c && f.name != 'main' && p.first_run() {
|
||||||
// TODO hack to make Volt compile without -embed_vlib
|
// TODO hack to make Volt compile without -embed_vlib
|
||||||
if f.name == 'darwin__nsstring' && p.pref.build_mode == default_mode {
|
if f.name == 'darwin__nsstring' && p.pref.build_mode == .default_mode {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.cgen.fns << fn_decl + ';'
|
p.cgen.fns << fn_decl + ';'
|
||||||
|
@ -77,7 +77,7 @@ mut:
|
|||||||
build_mode BuildMode
|
build_mode BuildMode
|
||||||
nofmt bool // disable vfmt
|
nofmt bool // disable vfmt
|
||||||
is_test bool // `v test string_test.v`
|
is_test bool // `v test string_test.v`
|
||||||
is_script bool // single file mode (`v program.v`), `fn main(){}` can be skipped
|
is_script bool // single file mode (`v program.v`), main function can be skipped
|
||||||
is_live bool // for hot code reloading
|
is_live bool // for hot code reloading
|
||||||
is_so bool
|
is_so bool
|
||||||
is_prof bool // benchmark every function
|
is_prof bool // benchmark every function
|
||||||
@ -92,6 +92,7 @@ mut:
|
|||||||
sanitize bool // use Clang's new "-fsanitize" option
|
sanitize bool // use Clang's new "-fsanitize" option
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
args := os.args
|
args := os.args
|
||||||
// Print the version and exit.
|
// Print the version and exit.
|
||||||
@ -108,7 +109,7 @@ fn main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO quit if the compiler is too old
|
// TODO quit if the compiler is too old
|
||||||
// u := os.file_last_mod_unix('/var/tmp/alex')
|
// u := os.file_last_mod_unix('v')
|
||||||
// Create a temp directory if it's not there.
|
// Create a temp directory if it's not there.
|
||||||
if !os.file_exists(TmpPath) {
|
if !os.file_exists(TmpPath) {
|
||||||
os.mkdir(TmpPath)
|
os.mkdir(TmpPath)
|
||||||
@ -242,23 +243,23 @@ 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')
|
||||||
}
|
}
|
||||||
// TODO remove ugly .c include once V has its own json parser
|
// TODO remove ugly .c include once V has its own json parser
|
||||||
// Embed cjson either in embedvlib or in json.o
|
// Embed cjson either in embedvlib or in json.o
|
||||||
if imports_json && v.pref.build_mode == embed_vlib ||
|
if imports_json && v.pref.build_mode == .embed_vlib ||
|
||||||
(v.pref.build_mode == build && v.out_name.contains('json.o')) {
|
(v.pref.build_mode == .build && v.out_name.contains('json.o')) {
|
||||||
cgen.genln('#include "cJSON.c" ')
|
cgen.genln('#include "cJSON.c" ')
|
||||||
}
|
}
|
||||||
// We need the cjson header for all the json decoding user will do in default mode
|
// We need the cjson header for all the json decoding user will do in default mode
|
||||||
if v.pref.build_mode == default_mode {
|
if v.pref.build_mode == .default_mode {
|
||||||
if imports_json {
|
if imports_json {
|
||||||
cgen.genln('#include "cJSON.h"')
|
cgen.genln('#include "cJSON.h"')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.pref.build_mode == embed_vlib || v.pref.build_mode == default_mode {
|
if v.pref.build_mode == .embed_vlib || v.pref.build_mode == .default_mode {
|
||||||
// If we declare these for all modes, then when running `v a.v` we'll get
|
// If we declare these for all modes, then when running `v a.v` we'll get
|
||||||
// `/usr/bin/ld: multiple definition of 'total_m'`
|
// `/usr/bin/ld: multiple definition of 'total_m'`
|
||||||
// TODO
|
// TODO
|
||||||
@ -303,7 +304,7 @@ void init_consts();')
|
|||||||
dd := d.str()
|
dd := d.str()
|
||||||
cgen.lines.set(defs_pos, dd)// TODO `def.str()` doesn't compile
|
cgen.lines.set(defs_pos, dd)// TODO `def.str()` doesn't compile
|
||||||
// if v.build_mode in [.default, .embed_vlib] {
|
// if v.build_mode in [.default, .embed_vlib] {
|
||||||
if v.pref.build_mode == default_mode || v.pref.build_mode == embed_vlib {
|
if v.pref.build_mode == .default_mode || v.pref.build_mode == .embed_vlib {
|
||||||
// vlib can't have `init_consts()`
|
// vlib can't have `init_consts()`
|
||||||
cgen.genln('void init_consts() { g_str_buf=malloc(1000); ${cgen.consts_init.join_lines()} }')
|
cgen.genln('void init_consts() { g_str_buf=malloc(1000); ${cgen.consts_init.join_lines()} }')
|
||||||
// _STR function can't be defined in vlib
|
// _STR function can't be defined in vlib
|
||||||
@ -343,7 +344,7 @@ string _STR_TMP(const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
// Make sure the main function exists
|
// Make sure the main function exists
|
||||||
// Obviously we don't need it in libraries
|
// Obviously we don't need it in libraries
|
||||||
if v.pref.build_mode != build {
|
if v.pref.build_mode != .build {
|
||||||
if !v.table.main_exists() && !v.pref.is_test {
|
if !v.table.main_exists() && !v.pref.is_test {
|
||||||
// It can be skipped in single file programs
|
// It can be skipped in single file programs
|
||||||
if v.pref.is_script {
|
if v.pref.is_script {
|
||||||
@ -424,7 +425,7 @@ fn (c &V) cc_windows_cross() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut libs := ''
|
mut libs := ''
|
||||||
if c.pref.build_mode == default_mode {
|
if c.pref.build_mode == .default_mode {
|
||||||
libs = '$TmpPath/vlib/builtin.o'
|
libs = '$TmpPath/vlib/builtin.o'
|
||||||
if !os.file_exists(libs) {
|
if !os.file_exists(libs) {
|
||||||
println('`builtin.o` not found')
|
println('`builtin.o` not found')
|
||||||
@ -462,7 +463,7 @@ fn (c &V) cc_windows_cross() {
|
|||||||
println('Cross compilation for Windows failed. Make sure you have clang installed.')
|
println('Cross compilation for Windows failed. Make sure you have clang installed.')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
if c.pref.build_mode != build {
|
if c.pref.build_mode != .build {
|
||||||
link_cmd := 'lld-link $obj_name $winroot/lib/libcmt.lib ' +
|
link_cmd := 'lld-link $obj_name $winroot/lib/libcmt.lib ' +
|
||||||
'$winroot/lib/libucrt.lib $winroot/lib/kernel32.lib $winroot/lib/libvcruntime.lib ' +
|
'$winroot/lib/libucrt.lib $winroot/lib/kernel32.lib $winroot/lib/libvcruntime.lib ' +
|
||||||
'$winroot/lib/uuid.lib'
|
'$winroot/lib/uuid.lib'
|
||||||
@ -507,13 +508,13 @@ fn (v mut V) cc() {
|
|||||||
a << '-g'
|
a << '-g'
|
||||||
}
|
}
|
||||||
mut libs := ''// builtin.o os.o http.o etc
|
mut libs := ''// builtin.o os.o http.o etc
|
||||||
if v.pref.build_mode == build {
|
if v.pref.build_mode == .build {
|
||||||
a << '-c'
|
a << '-c'
|
||||||
}
|
}
|
||||||
else if v.pref.build_mode == embed_vlib {
|
else if v.pref.build_mode == .embed_vlib {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
else if v.pref.build_mode == default_mode {
|
else if v.pref.build_mode == .default_mode {
|
||||||
libs = '$TmpPath/vlib/builtin.o'
|
libs = '$TmpPath/vlib/builtin.o'
|
||||||
if !os.file_exists(libs) {
|
if !os.file_exists(libs) {
|
||||||
println('`builtin.o` not found')
|
println('`builtin.o` not found')
|
||||||
@ -568,7 +569,7 @@ mut args := ''
|
|||||||
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
|
||||||
@ -595,7 +596,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')
|
||||||
@ -614,7 +615,9 @@ mut args := ''
|
|||||||
}
|
}
|
||||||
println('linux cross compilation done. resulting binary: "$v.out_name"')
|
println('linux cross compilation done. resulting binary: "$v.out_name"')
|
||||||
}
|
}
|
||||||
//os.rm('$TmpPath/$v.out_name_c')
|
if v.out_name_c != 'v.c' {
|
||||||
|
os.rm('$TmpPath/$v.out_name_c')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) v_files_from_dir(dir string) []string {
|
fn (v &V) v_files_from_dir(dir string) []string {
|
||||||
@ -706,7 +709,7 @@ fn (v mut V) add_user_v_files() {
|
|||||||
p.parse()
|
p.parse()
|
||||||
}
|
}
|
||||||
// Parse lib imports
|
// Parse lib imports
|
||||||
if v.pref.build_mode == default_mode {
|
if v.pref.build_mode == .default_mode {
|
||||||
for i := 0; i < v.table.imports.len; i++ {
|
for i := 0; i < v.table.imports.len; i++ {
|
||||||
pkg := v.table.imports[i]
|
pkg := v.table.imports[i]
|
||||||
vfiles := v.v_files_from_dir('$TmpPath/vlib/$pkg')
|
vfiles := v.v_files_from_dir('$TmpPath/vlib/$pkg')
|
||||||
@ -741,7 +744,7 @@ fn (v mut V) add_user_v_files() {
|
|||||||
// If we are in default mode, we don't parse vlib .v files, but header .vh files in
|
// If we are in default mode, we don't parse vlib .v files, but header .vh files in
|
||||||
// TmpPath/vlib
|
// TmpPath/vlib
|
||||||
// These were generated by vfmt
|
// These were generated by vfmt
|
||||||
if v.pref.build_mode == default_mode || v.pref.build_mode == build {
|
if v.pref.build_mode == .default_mode || v.pref.build_mode == .build {
|
||||||
module_path = '$TmpPath/vlib/$pkg'
|
module_path = '$TmpPath/vlib/$pkg'
|
||||||
}
|
}
|
||||||
vfiles := v.v_files_from_dir(module_path)
|
vfiles := v.v_files_from_dir(module_path)
|
||||||
@ -793,23 +796,27 @@ fn new_v(args[]string) *V {
|
|||||||
target_os := get_arg(joined_args, 'os', '')
|
target_os := get_arg(joined_args, 'os', '')
|
||||||
mut out_name := get_arg(joined_args, 'o', 'a.out')
|
mut out_name := get_arg(joined_args, 'o', 'a.out')
|
||||||
// build mode
|
// build mode
|
||||||
mut build_mode := default_mode
|
mut build_mode := BuildMode.default_mode
|
||||||
if args.contains('-lib') {
|
if args.contains('-lib') {
|
||||||
build_mode = build
|
build_mode = .build
|
||||||
// v -lib ~/v/os => os.o
|
// v -lib ~/v/os => os.o
|
||||||
base := dir.all_after('/')
|
base := dir.all_after('/')
|
||||||
println('Building module ${base}...')
|
println('Building module ${base}...')
|
||||||
out_name = '$TmpPath/vlib/${base}.o'
|
//out_name = '$TmpPath/vlib/${base}.o'
|
||||||
|
out_name = base + '.o'
|
||||||
// Cross compiling? Use separate dirs for each os
|
// Cross compiling? Use separate dirs for each os
|
||||||
|
/*
|
||||||
if target_os != os.user_os() {
|
if target_os != os.user_os() {
|
||||||
os.mkdir('$TmpPath/vlib/$target_os')
|
os.mkdir('$TmpPath/vlib/$target_os')
|
||||||
out_name = '$TmpPath/vlib/$target_os/${base}.o'
|
out_name = '$TmpPath/vlib/$target_os/${base}.o'
|
||||||
println('Cross compiling $out_name')
|
println('target_os=$target_os user_os=${os.user_os()}')
|
||||||
|
println('!Cross compiling $out_name')
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
// TODO embed_vlib is temporarily the default mode. It's much slower.
|
// TODO embed_vlib is temporarily the default mode. It's much slower.
|
||||||
else if !args.contains('-embed_vlib') {
|
else if !args.contains('-embed_vlib') {
|
||||||
build_mode = embed_vlib
|
build_mode = .embed_vlib
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
is_test := dir.ends_with('_test.v')
|
is_test := dir.ends_with('_test.v')
|
||||||
@ -896,7 +903,7 @@ fn new_v(args[]string) *V {
|
|||||||
for builtin in builtins {
|
for builtin in builtins {
|
||||||
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
|
||||||
|
@ -46,6 +46,7 @@ mut:
|
|||||||
inside_const bool
|
inside_const bool
|
||||||
expr_var Var
|
expr_var Var
|
||||||
assigned_type string
|
assigned_type string
|
||||||
|
left_type string
|
||||||
tmp_cnt int
|
tmp_cnt int
|
||||||
// TODO all these options are copy-pasted from the V struct. Create a Settings struct instead?
|
// TODO all these options are copy-pasted from the V struct. Create a Settings struct instead?
|
||||||
// is_test bool
|
// is_test bool
|
||||||
@ -589,9 +590,10 @@ fn (p mut Parser) enum_decl(_enum_name string) {
|
|||||||
mut val := 0
|
mut val := 0
|
||||||
for p.tok == NAME {
|
for p.tok == NAME {
|
||||||
field := p.check_name()
|
field := p.check_name()
|
||||||
// name := '${p.pkg}__${enum_name}_$field'
|
mut name := '$field'
|
||||||
// name := '${enum_name}_$field'
|
if enum_name == 'BuildMode' {
|
||||||
name := '$field'
|
name = '${p.pkg}__${enum_name}_$field'
|
||||||
|
}
|
||||||
p.fgenln('')
|
p.fgenln('')
|
||||||
if p.run == RUN_MAIN {
|
if p.run == RUN_MAIN {
|
||||||
p.cgen.consts << '#define $name $val \n'
|
p.cgen.consts << '#define $name $val \n'
|
||||||
@ -1178,6 +1180,7 @@ fn (p mut Parser) bool_expression() string {
|
|||||||
fn (p mut Parser) bterm() string {
|
fn (p mut Parser) bterm() string {
|
||||||
ph := p.cgen.add_placeholder()
|
ph := p.cgen.add_placeholder()
|
||||||
mut typ := p.expression()
|
mut typ := p.expression()
|
||||||
|
p.left_type = typ
|
||||||
is_str := typ=='string'
|
is_str := typ=='string'
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
// if tok in [ EQ, GT, LT, LE, GE, NE] {
|
// if tok in [ EQ, GT, LT, LE, GE, NE] {
|
||||||
@ -1207,7 +1210,7 @@ fn (p mut Parser) bterm() string {
|
|||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
// also called on *, &
|
// also called on *, &, . (enum)
|
||||||
fn (p mut Parser) name_expr() string {
|
fn (p mut Parser) name_expr() string {
|
||||||
p.log('\nname expr() pass=$p.run tok=${p.tok.str()} $p.lit')
|
p.log('\nname expr() pass=$p.run tok=${p.tok.str()} $p.lit')
|
||||||
// print('known type:')
|
// print('known type:')
|
||||||
@ -1217,6 +1220,7 @@ fn (p mut Parser) name_expr() string {
|
|||||||
hack_tok := p.tok
|
hack_tok := p.tok
|
||||||
hack_lit := p.lit
|
hack_lit := p.lit
|
||||||
// amp
|
// amp
|
||||||
|
|
||||||
ptr := p.tok == AMP
|
ptr := p.tok == AMP
|
||||||
deref := p.tok == MUL
|
deref := p.tok == MUL
|
||||||
if ptr || deref {
|
if ptr || deref {
|
||||||
@ -1243,6 +1247,17 @@ fn (p mut Parser) name_expr() string {
|
|||||||
is_c_struct_init = true
|
is_c_struct_init = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// enum value? (`color == .green`)
|
||||||
|
if p.tok == DOT {
|
||||||
|
//println('got enum dot val $p.left_type pass=$p.run $p.scanner.line_nr left=$p.left_type')
|
||||||
|
T := p.find_type(p.left_type)
|
||||||
|
if T.is_enum {
|
||||||
|
p.check(DOT)
|
||||||
|
val := p.check_name()
|
||||||
|
p.gen(p.pkg + '__' + p.left_type + '_' + val)
|
||||||
|
}
|
||||||
|
return p.left_type
|
||||||
|
}
|
||||||
// //////////////////////////
|
// //////////////////////////
|
||||||
// module ?
|
// module ?
|
||||||
// Allow shadowing (gg = gg.newcontext(); gg.draw_triangle())
|
// Allow shadowing (gg = gg.newcontext(); gg.draw_triangle())
|
||||||
@ -1454,23 +1469,28 @@ fn (p mut Parser) var_expr(v Var) string {
|
|||||||
}
|
}
|
||||||
if typ != 'int' {
|
if typ != 'int' {
|
||||||
if !p.pref.translated && !is_number_type(typ) {
|
if !p.pref.translated && !is_number_type(typ) {
|
||||||
// if T.parent != 'int' {
|
|
||||||
p.error('cannot ++/-- value of type `$typ`')
|
p.error('cannot ++/-- value of type `$typ`')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.gen(p.tok.str())
|
p.gen(p.tok.str())
|
||||||
p.fgen(p.tok.str())
|
p.fgen(p.tok.str())
|
||||||
p.next()// ++
|
p.next()// ++/--
|
||||||
// allow a := c++ in translated
|
// allow `a := c++` in translated code
|
||||||
if p.pref.translated {
|
if p.pref.translated {
|
||||||
return p.index_expr(typ, fn_ph)
|
//return p.index_expr(typ, fn_ph)
|
||||||
// return typ
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 'void'
|
return 'void'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typ = p.index_expr(typ, fn_ph)
|
typ = p.index_expr(typ, fn_ph)
|
||||||
|
// TODO hack to allow `foo.bar[0] = 2`
|
||||||
|
if p.tok == DOT {
|
||||||
|
for p.tok == DOT {
|
||||||
|
typ = p.dot(typ, fn_ph)
|
||||||
|
}
|
||||||
|
typ = p.index_expr(typ, fn_ph)
|
||||||
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1485,9 +1505,9 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
|||||||
field_name := p.lit
|
field_name := p.lit
|
||||||
p.fgen(field_name)
|
p.fgen(field_name)
|
||||||
p.log('dot() field_name=$field_name typ=$str_typ')
|
p.log('dot() field_name=$field_name typ=$str_typ')
|
||||||
if p.fileis('hi_test') {
|
//if p.fileis('main.v') {
|
||||||
println('dot() field_name=$field_name typ=$str_typ')
|
//println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}')
|
||||||
}
|
//}
|
||||||
typ := p.find_type(str_typ)
|
typ := p.find_type(str_typ)
|
||||||
if typ.name.len == 0 {
|
if typ.name.len == 0 {
|
||||||
p.error('dot(): cannot find type `$str_typ`')
|
p.error('dot(): cannot find type `$str_typ`')
|
||||||
@ -1500,7 +1520,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
|||||||
opt_type := typ.name.substr(7, typ.name.len)
|
opt_type := typ.name.substr(7, typ.name.len)
|
||||||
p.error('unhandled option type: $opt_type?')
|
p.error('unhandled option type: $opt_type?')
|
||||||
}
|
}
|
||||||
println('dot():')
|
println('error in dot():')
|
||||||
println('fields:')
|
println('fields:')
|
||||||
for field in typ.fields {
|
for field in typ.fields {
|
||||||
println(field.name)
|
println(field.name)
|
||||||
@ -1564,17 +1584,17 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
|||||||
// return typ.name.replace('array_', '')
|
// return typ.name.replace('array_', '')
|
||||||
return typ.name.right(6)
|
return typ.name.right(6)
|
||||||
}
|
}
|
||||||
if false && p.tok == LSBR {
|
//if false && p.tok == LSBR {
|
||||||
// if is_indexer {
|
// if is_indexer {
|
||||||
return p.index_expr(method.typ, method_ph)
|
//return p.index_expr(method.typ, method_ph)
|
||||||
}
|
//}
|
||||||
return method.typ
|
return method.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) index_expr(typ string, fn_ph int) string {
|
fn (p mut Parser) index_expr(typ string, fn_ph int) string {
|
||||||
if p.fileis('int_test') {
|
//if p.fileis('main.v') {
|
||||||
println('index expr typ=$typ')
|
//println('index expr typ=$typ')
|
||||||
}
|
//}
|
||||||
// a[0]
|
// a[0]
|
||||||
v := p.expr_var
|
v := p.expr_var
|
||||||
is_map := typ.starts_with('map_')
|
is_map := typ.starts_with('map_')
|
||||||
@ -1688,16 +1708,13 @@ fn (p mut Parser) index_expr(typ string, fn_ph int) string {
|
|||||||
p.tok == MULT_ASSIGN || p.tok == DIV_ASSIGN || p.tok == XOR_ASSIGN || p.tok == MOD_ASSIGN ||
|
p.tok == MULT_ASSIGN || p.tok == DIV_ASSIGN || p.tok == XOR_ASSIGN || p.tok == MOD_ASSIGN ||
|
||||||
p.tok == OR_ASSIGN || p.tok == AND_ASSIGN || p.tok == RIGHT_SHIFT_ASSIGN ||
|
p.tok == OR_ASSIGN || p.tok == AND_ASSIGN || p.tok == RIGHT_SHIFT_ASSIGN ||
|
||||||
p.tok == LEFT_SHIFT_ASSIGN {
|
p.tok == LEFT_SHIFT_ASSIGN {
|
||||||
if is_map || is_arr {
|
|
||||||
// Don't generate indexer right away, but assign it to tmp
|
|
||||||
// p.cgen.start_tmp()
|
|
||||||
}
|
|
||||||
if is_indexer && is_str && !p.builtin_pkg {
|
if is_indexer && is_str && !p.builtin_pkg {
|
||||||
p.error('strings are immutable')
|
p.error('strings are immutable')
|
||||||
}
|
}
|
||||||
// println('111 "$p.cgen.cur_line"')
|
// println('111 "$p.cgen.cur_line"')
|
||||||
assign_pos := p.cgen.cur_line.len
|
assign_pos := p.cgen.cur_line.len
|
||||||
p.assigned_type = typ
|
p.assigned_type = typ
|
||||||
|
p.left_type = typ
|
||||||
p.assign_statement(v, fn_ph, is_indexer && (is_map || is_arr))
|
p.assign_statement(v, fn_ph, is_indexer && (is_map || is_arr))
|
||||||
// m[key] = val
|
// m[key] = val
|
||||||
if is_indexer && (is_map || is_arr) {
|
if is_indexer && (is_map || is_arr) {
|
||||||
@ -1833,7 +1850,7 @@ fn (p mut Parser) expression() string {
|
|||||||
p.check_types(p.expression(), typ)
|
p.check_types(p.expression(), typ)
|
||||||
return 'int'
|
return 'int'
|
||||||
}
|
}
|
||||||
if p.tok == DOT {
|
if p.tok == DOT {
|
||||||
for p.tok == DOT {
|
for p.tok == DOT {
|
||||||
typ = p.dot(typ, 0)
|
typ = p.dot(typ, 0)
|
||||||
}
|
}
|
||||||
@ -2669,7 +2686,7 @@ fn (p mut Parser) chash() {
|
|||||||
else if hash.contains('embed') {
|
else if hash.contains('embed') {
|
||||||
pos := hash.index('embed') + 5
|
pos := hash.index('embed') + 5
|
||||||
file := hash.right(pos)
|
file := hash.right(pos)
|
||||||
if p.pref.build_mode != default_mode {
|
if p.pref.build_mode != BuildMode.default_mode {
|
||||||
p.genln('#include $file')
|
p.genln('#include $file')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,6 @@ enum AccessMod {
|
|||||||
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 mutable both inside and outside (not recommended to use, that's why it's so verbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TypeCategory {
|
|
||||||
TYPE_STRUCT
|
|
||||||
T_CAT_FN
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
mut:
|
mut:
|
||||||
pkg string
|
pkg string
|
||||||
@ -37,8 +32,6 @@ mut:
|
|||||||
fields []Var
|
fields []Var
|
||||||
methods []Fn
|
methods []Fn
|
||||||
parent string
|
parent string
|
||||||
cat TypeCategory
|
|
||||||
gen_types []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.FILE
|
||||||
is_interface bool
|
is_interface bool
|
||||||
@ -369,6 +362,7 @@ fn (t &Type) find_method(name string) Fn {
|
|||||||
return Fn{}
|
return Fn{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
fn (t mut Type) add_gen_type(type_name string) {
|
fn (t mut Type) add_gen_type(type_name string) {
|
||||||
// println('add_gen_type($s)')
|
// println('add_gen_type($s)')
|
||||||
if t.gen_types.contains(type_name) {
|
if t.gen_types.contains(type_name) {
|
||||||
@ -376,6 +370,7 @@ fn (t mut Type) add_gen_type(type_name string) {
|
|||||||
}
|
}
|
||||||
t.gen_types << type_name
|
t.gen_types << type_name
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn (p &Parser) find_type(name string) *Type {
|
fn (p &Parser) find_type(name string) *Type {
|
||||||
typ := p.table.find_type(name)
|
typ := p.table.find_type(name)
|
||||||
|
44
vlib/builtin/struct_test.v
Normal file
44
vlib/builtin/struct_test.v
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
struct A{
|
||||||
|
mut:
|
||||||
|
val int
|
||||||
|
nums []int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct B{
|
||||||
|
mut:
|
||||||
|
a A
|
||||||
|
}
|
||||||
|
struct C {
|
||||||
|
mut:
|
||||||
|
b B
|
||||||
|
nums []int
|
||||||
|
as []A
|
||||||
|
num int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_struct_levels() {
|
||||||
|
mut c := C{}
|
||||||
|
assert c.nums.len == 0
|
||||||
|
c.nums << 3
|
||||||
|
assert c.nums.len == 1
|
||||||
|
assert c.nums[0] == 3
|
||||||
|
c.nums[0] = 4
|
||||||
|
assert c.nums[0] == 4
|
||||||
|
c.b.a.val = 34
|
||||||
|
assert c.b.a.val == 34
|
||||||
|
c.b.a.nums = [0;0]
|
||||||
|
c.b.a.nums << 0
|
||||||
|
c.b.a.nums << 2
|
||||||
|
assert c.b.a.nums.len == 2
|
||||||
|
assert c.b.a.nums[0] == 0
|
||||||
|
assert c.b.a.nums[1] == 2
|
||||||
|
c.b.a.nums [0] = 7
|
||||||
|
assert c.b.a.nums[0] == 7
|
||||||
|
c.as << A{val:8}
|
||||||
|
assert c.as.len == 1
|
||||||
|
assert c.as[0].val == 8
|
||||||
|
c.num = 20
|
||||||
|
assert c.num == 20
|
||||||
|
c.as[0].val = 10
|
||||||
|
assert c.as[0].val == 10
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user