mirror of
https://github.com/vlang/v.git
synced 2025-09-18 03:46:36 -04:00
This commit is contained in:
parent
d1dcffa928
commit
582ec6e03c
@ -883,27 +883,54 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fn_name.ends_with('from_string') {
|
}
|
||||||
enum_name := fn_name.all_before('__static__')
|
// Enum.from_string, `mod.Enum.from_string('item')`, `Enum.from_string('item')`
|
||||||
full_enum_name := if !enum_name.contains('.') {
|
if !found && fn_name.ends_with('__static__from_string') {
|
||||||
c.mod + '.' + enum_name
|
enum_name := fn_name.all_before('__static__')
|
||||||
} else {
|
mut full_enum_name := if !enum_name.contains('.') {
|
||||||
enum_name
|
c.mod + '.' + enum_name
|
||||||
}
|
} else {
|
||||||
idx := c.table.type_idxs[full_enum_name]
|
enum_name
|
||||||
ret_typ := ast.Type(idx).set_flag(.option)
|
}
|
||||||
if node.args.len != 1 {
|
mut idx := c.table.type_idxs[full_enum_name]
|
||||||
c.error('expected 1 argument, but got ${node.args.len}', node.pos)
|
if idx > 0 {
|
||||||
} else {
|
// is from another mod.
|
||||||
node.args[0].typ = c.expr(mut node.args[0].expr)
|
if enum_name.contains('.') {
|
||||||
if node.args[0].typ != ast.string_type {
|
if !c.check_type_and_visibility(full_enum_name, idx, .enum_, node.pos) {
|
||||||
styp := c.table.type_to_str(node.args[0].typ)
|
return ast.void_type
|
||||||
c.error('expected `string` argument, but got `${styp}`', node.pos)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.return_type = ret_typ
|
} else if !enum_name.contains('.') {
|
||||||
return ret_typ
|
// find from another mods.
|
||||||
|
for import_sym in c.file.imports {
|
||||||
|
full_enum_name = '${import_sym.mod}.${enum_name}'
|
||||||
|
idx = c.table.type_idxs[full_enum_name]
|
||||||
|
if idx < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !c.check_type_and_visibility(full_enum_name, idx, .enum_, node.pos) {
|
||||||
|
return ast.void_type
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if idx == 0 {
|
||||||
|
c.error('unknown enum `${enum_name}`', node.pos)
|
||||||
|
return ast.void_type
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_typ := ast.Type(idx).set_flag(.option)
|
||||||
|
if node.args.len != 1 {
|
||||||
|
c.error('expected 1 argument, but got ${node.args.len}', node.pos)
|
||||||
|
} else {
|
||||||
|
node.args[0].typ = c.expr(mut node.args[0].expr)
|
||||||
|
if node.args[0].typ != ast.string_type {
|
||||||
|
styp := c.table.type_to_str(node.args[0].typ)
|
||||||
|
c.error('expected `string` argument, but got `${styp}`', node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.return_type = ret_typ
|
||||||
|
return ret_typ
|
||||||
}
|
}
|
||||||
mut is_native_builtin := false
|
mut is_native_builtin := false
|
||||||
if !found && c.pref.backend == .native {
|
if !found && c.pref.backend == .native {
|
||||||
@ -1622,6 +1649,24 @@ fn (mut c Checker) cast_to_fixed_array_ret(typ ast.Type, sym ast.TypeSymbol) ast
|
|||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checks if a type from another module is is expected and visible(`is_pub`)
|
||||||
|
fn (mut c Checker) check_type_and_visibility(name string, type_idx int, expected_kind &ast.Kind, pos &token.Pos) bool {
|
||||||
|
mut sym := c.table.sym_by_idx(type_idx)
|
||||||
|
if sym.kind == .alias {
|
||||||
|
parent_type := (sym.info as ast.Alias).parent_type
|
||||||
|
sym = c.table.sym(parent_type)
|
||||||
|
}
|
||||||
|
if sym.kind != expected_kind {
|
||||||
|
c.error('expected ${expected_kind}, but `${name}` is ${sym.kind}', pos)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !sym.is_pub {
|
||||||
|
c.error('module `${sym.mod}` type `${sym.name}` is private', pos)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
||||||
left_type := c.expr(mut node.left)
|
left_type := c.expr(mut node.left)
|
||||||
if left_type == ast.void_type {
|
if left_type == ast.void_type {
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:3:8: warning: module 'mod' is imported but never used
|
||||||
|
1 | module main
|
||||||
|
2 |
|
||||||
|
3 | import mod { MyEnum, MyStruct }
|
||||||
|
| ~~~
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:3:14: error: module `mod` type `MyEnum` is private
|
||||||
|
1 | module main
|
||||||
|
2 |
|
||||||
|
3 | import mod { MyEnum, MyStruct }
|
||||||
|
| ~~~~~~
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:6:7: error: module `mod` type `mod.MyEnum` is private
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
6 | _ := MyEnum.from_string('item1')
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
7 | _ := MyStruct.from_string('item1')
|
||||||
|
8 | }
|
||||||
|
vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:6:4: error: assignment mismatch: 1 variable(s) but `MyEnum.from_string()` returns 0 value(s)
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
6 | _ := MyEnum.from_string('item1')
|
||||||
|
| ~~
|
||||||
|
7 | _ := MyStruct.from_string('item1')
|
||||||
|
8 | }
|
||||||
|
vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:7:7: error: expected enum, but `mod.MyStruct` is struct
|
||||||
|
5 | fn main() {
|
||||||
|
6 | _ := MyEnum.from_string('item1')
|
||||||
|
7 | _ := MyStruct.from_string('item1')
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
8 | }
|
||||||
|
vlib/v/checker/tests/modules/enum_from_string_in_different_mods/src/main.v:7:4: error: assignment mismatch: 1 variable(s) but `MyStruct.from_string()` returns 0 value(s)
|
||||||
|
5 | fn main() {
|
||||||
|
6 | _ := MyEnum.from_string('item1')
|
||||||
|
7 | _ := MyStruct.from_string('item1')
|
||||||
|
| ~~
|
||||||
|
8 | }
|
@ -0,0 +1,8 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import mod { MyEnum, MyStruct }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
_ := MyEnum.from_string('item1')
|
||||||
|
_ := MyStruct.from_string('item1')
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
module mod
|
||||||
|
|
||||||
|
enum MyEnum {
|
||||||
|
item1
|
||||||
|
item2
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MyStruct {}
|
@ -0,0 +1 @@
|
|||||||
|
1
|
@ -1150,12 +1150,22 @@ fn should_use_indent_func(kind ast.Kind) bool {
|
|||||||
|
|
||||||
fn (mut g Gen) gen_enum_static_from_string(fn_name string) {
|
fn (mut g Gen) gen_enum_static_from_string(fn_name string) {
|
||||||
enum_name := fn_name.all_before('__static__')
|
enum_name := fn_name.all_before('__static__')
|
||||||
mod_enum_name := if !enum_name.contains('.') {
|
mut mod_enum_name := if !enum_name.contains('.') {
|
||||||
g.cur_mod.name + '.' + enum_name
|
g.cur_mod.name + '.' + enum_name
|
||||||
} else {
|
} else {
|
||||||
enum_name
|
enum_name
|
||||||
}
|
}
|
||||||
idx := g.table.type_idxs[mod_enum_name]
|
mut idx := g.table.type_idxs[mod_enum_name]
|
||||||
|
if idx == 0 && (enum_name.contains('.') || enum_name[0].is_capital()) {
|
||||||
|
// no cur mod, find from another mods.
|
||||||
|
for import_sym in g.file.imports {
|
||||||
|
mod_enum_name = '${import_sym.mod}.${enum_name}'
|
||||||
|
idx = g.table.type_idxs[mod_enum_name]
|
||||||
|
if idx > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
enum_typ := ast.Type(idx)
|
enum_typ := ast.Type(idx)
|
||||||
enum_styp := g.typ(enum_typ)
|
enum_styp := g.typ(enum_typ)
|
||||||
option_enum_typ := ast.Type(idx).set_flag(.option)
|
option_enum_typ := ast.Type(idx).set_flag(.option)
|
||||||
@ -1164,9 +1174,10 @@ fn (mut g Gen) gen_enum_static_from_string(fn_name string) {
|
|||||||
enum_field_vals := g.table.get_enum_field_vals(mod_enum_name)
|
enum_field_vals := g.table.get_enum_field_vals(mod_enum_name)
|
||||||
|
|
||||||
mut fn_builder := strings.new_builder(512)
|
mut fn_builder := strings.new_builder(512)
|
||||||
g.definitions.writeln('static ${option_enum_styp} ${fn_name}(string name); // auto')
|
fn_name_no_dots := util.no_dots(fn_name)
|
||||||
|
g.definitions.writeln('static ${option_enum_styp} ${fn_name_no_dots}(string name); // auto')
|
||||||
|
|
||||||
fn_builder.writeln('static ${option_enum_styp} ${fn_name}(string name) {')
|
fn_builder.writeln('static ${option_enum_styp} ${fn_name_no_dots}(string name) {')
|
||||||
fn_builder.writeln('\t${option_enum_styp} t1;')
|
fn_builder.writeln('\t${option_enum_styp} t1;')
|
||||||
fn_builder.writeln('\tbool exists = false;')
|
fn_builder.writeln('\tbool exists = false;')
|
||||||
fn_builder.writeln('\tint inx = 0;')
|
fn_builder.writeln('\tint inx = 0;')
|
||||||
|
@ -1803,7 +1803,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||||||
g.gen_enum_static_from_string(node.name)
|
g.gen_enum_static_from_string(node.name)
|
||||||
g.str_fn_names << node.name
|
g.str_fn_names << node.name
|
||||||
}
|
}
|
||||||
g.write('${node.name}(')
|
g.write('${util.no_dots(node.name)}(')
|
||||||
g.call_args(node)
|
g.call_args(node)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import mod { MyEnum }
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
item1 := MyEnum.from_string('item1')?
|
||||||
|
assert item1 == MyEnum.item1
|
||||||
|
item2 := mod.MyEnum.from_string('item2')?
|
||||||
|
assert item2 == MyEnum.item2
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
module mod
|
||||||
|
|
||||||
|
pub enum MyEnum {
|
||||||
|
item1
|
||||||
|
item2
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
1
|
Loading…
x
Reference in New Issue
Block a user