Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/tools/vself.v
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module main

import os
import os.cmdline
import v.pref
import v.util.recompilation

const args_ = arguments()
Expand All @@ -10,7 +11,7 @@ const is_debug = args_.contains('-debug')
// support a renamed `v` executable too:
const vexe = os.getenv_opt('VEXE') or { @VEXE }

const vroot = os.dir(vexe)
const vroot = pref.vroot_from_vexe(vexe)
const vself_flags_with_values = ['-o', '-os', '-cc', '-gc', '-cf', '-cflags', '-d', '-define']

fn main() {
Expand Down
77 changes: 50 additions & 27 deletions vlib/v/ast/table.v
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ pub fn (t &Table) get_type_methods(typ Type) []Fn {
for method in methods {
seen_method_names[method.name] = true
}
for ts.parent_idx != 0 {
for ts.parent_idx > 0 && ts.parent_idx < t.type_symbols.len {
ts = t.type_symbols[ts.parent_idx]
for method in ts.get_methods() {
if method.name !in seen_method_names {
Expand All @@ -479,9 +479,12 @@ pub fn (t &Table) find_method(s &TypeSymbol, name string) !Fn {
return method
}
if ts.kind == .generic_inst {
parent_sym := t.sym(new_type((ts.info as GenericInst).parent_idx))
if method := parent_sym.find_method_with_generic_parent(name) {
return method
parent_idx := (ts.info as GenericInst).parent_idx
if parent_idx > 0 && parent_idx < t.type_symbols.len {
parent_sym := t.sym(new_type(parent_idx))
if method := parent_sym.find_method_with_generic_parent(name) {
return method
}
}
return error('unknown method')
}
Expand All @@ -492,7 +495,16 @@ pub fn (t &Table) find_method(s &TypeSymbol, name string) !Fn {
return err
}
}
if ts.parent_idx == 0 {
if ts.info is Alias {
parent_idx := ts.info.parent_type.idx()
if parent_idx > 0 && parent_idx < t.type_symbols.len && parent_idx != ts.idx {
parent_sym := t.sym(ts.info.parent_type)
if method := t.find_method(parent_sym, name) {
return method
}
}
}
if ts.parent_idx <= 0 || ts.parent_idx >= t.type_symbols.len {
// Also try Struct/Interface/SumType parent_type for generic concrete types
// whose parent_idx is 0 but have parent_type set.
has_parent_type := (ts.kind == .struct && (ts.info as Struct).parent_type != 0)
Expand Down Expand Up @@ -755,31 +767,33 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) !StructField {
}
}
GenericInst {
parent_sym := t.sym(new_type(ts.info.parent_idx))
if field := t.find_field(parent_sym, name) {
match parent_sym.info {
Struct, Interface, SumType {
mut table := global_table
generic_names := parent_sym.info.generic_types.map(t.sym(it).name)
if generic_names.len == ts.info.concrete_types.len {
mut resolved_field := field
if ft := table.convert_generic_type(field.typ, generic_names,
ts.info.concrete_types)
{
resolved_field.typ = ft
}
if fut := table.convert_generic_type(field.unaliased_typ,
generic_names, ts.info.concrete_types)
{
resolved_field.unaliased_typ = fut
if ts.info.parent_idx > 0 && ts.info.parent_idx < t.type_symbols.len {
parent_sym := t.sym(new_type(ts.info.parent_idx))
if field := t.find_field(parent_sym, name) {
match parent_sym.info {
Struct, Interface, SumType {
mut table := global_table
generic_names := parent_sym.info.generic_types.map(t.sym(it).name)
if generic_names.len == ts.info.concrete_types.len {
mut resolved_field := field
if ft := table.convert_generic_type(field.typ, generic_names,
ts.info.concrete_types)
{
resolved_field.typ = ft
}
if fut := table.convert_generic_type(field.unaliased_typ,
generic_names, ts.info.concrete_types)
{
resolved_field.unaliased_typ = fut
}
return resolved_field
}
return resolved_field
}
else {}
}
else {}
}

return field
return field
}
}
}
SumType {
Expand All @@ -790,10 +804,19 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) !StructField {
missing_variants := t.find_missing_variants(ts.info, name)
return error('field `${name}` does not exist or have the same type in these sumtype `${ts.name}` variants: ${missing_variants}')
}
Alias {
parent_idx := ts.info.parent_type.idx()
if parent_idx > 0 && parent_idx < t.type_symbols.len && parent_idx != ts.idx {
parent_sym := t.sym(ts.info.parent_type)
if field := t.find_field(parent_sym, name) {
return field
}
}
}
else {}
}

if ts.parent_idx == 0 {
if ts.parent_idx <= 0 || ts.parent_idx >= t.type_symbols.len {
break
}
ts = t.type_symbols[ts.parent_idx]
Expand Down
58 changes: 34 additions & 24 deletions vlib/v/ast/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,7 @@ pub fn (mut t Table) register_builtin_type_symbols() {
t.register_sym(kind: .bool, name: 'bool', cname: 'bool', mod: 'builtin', is_pub: true) // 19
t.register_sym(kind: .none, name: 'none', cname: 'none', mod: 'builtin', is_pub: true) // 20
t.register_sym(
kind: .string
kind: Kind.string
name: 'string'
cname: 'string'
mod: 'builtin'
Expand Down Expand Up @@ -2040,7 +2040,7 @@ pub fn (t &TypeSymbol) embed_name() string {
}

pub fn (t &TypeSymbol) has_method(name string) bool {
for mut method in unsafe { t.methods } {
for method in unsafe { t.methods } {
if method.name.len == name.len && method.name == name {
return true
}
Expand All @@ -2054,7 +2054,7 @@ pub fn (t &TypeSymbol) has_method_with_generic_parent(name string) bool {
}

pub fn (t &TypeSymbol) find_method(name string) ?Fn {
for mut method in unsafe { t.methods } {
for method in unsafe { t.methods } {
if method.name.len == name.len && method.name == name {
return method
}
Expand Down Expand Up @@ -2393,6 +2393,9 @@ pub fn (table &Table) structured_receiver_method_rejects_voidptr(actual_type Typ
key := receiver_pattern_method_key(actual.parent_idx, name)
methods := table.structured_receiver_methods[key] or { return false }
for method in methods {
if method.params.len == 0 {
continue
}
receiver_generic_names :=
table.structured_receiver_generic_pattern_names(method.receiver_type)
if receiver_generic_names.len > 0
Expand All @@ -2408,6 +2411,9 @@ pub fn (table &Table) find_structured_receiver_method_with_types(actual_type Typ
key := receiver_pattern_method_key(actual.parent_idx, name)
methods := table.structured_receiver_methods[key] or { return none }
for method in methods {
if method.params.len == 0 {
continue
}
receiver_generic_names :=
table.structured_receiver_generic_pattern_names(method.receiver_type)
if receiver_generic_names.len == 0 || receiver_generic_names.len > method.generic_names.len
Expand Down Expand Up @@ -2465,17 +2471,19 @@ pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
}
GenericInst {
generic_inst_parent_idx = t.info.parent_idx
parent_sym := table.sym(new_type(generic_inst_parent_idx))
match parent_sym.info {
Struct, Interface, SumType {
generic_names = parent_sym.info.generic_types.map(table.sym(it).name)
concrete_types = t.info.concrete_types.clone()
}
FnType {
generic_names = parent_sym.info.func.generic_names.clone()
concrete_types = t.info.concrete_types.clone()
if generic_inst_parent_idx > 0 {
parent_sym := table.sym(new_type(generic_inst_parent_idx))
match parent_sym.info {
Struct, Interface, SumType {
generic_names = parent_sym.info.generic_types.map(table.sym(it).name)
concrete_types = t.info.concrete_types.clone()
}
FnType {
generic_names = parent_sym.info.func.generic_names.clone()
concrete_types = t.info.concrete_types.clone()
}
else {}
}
else {}
}
}
else {}
Expand All @@ -2487,10 +2495,12 @@ pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
}
return m
}
if m := table.find_structured_receiver_method(new_type(t.idx), name) {
return m
if t.idx > 0 {
if m := table.find_structured_receiver_method(new_type(t.idx), name) {
return m
}
}
if generic_inst_parent_idx != 0 {
if generic_inst_parent_idx > 0 && generic_inst_parent_idx < table.type_symbols.len {
mut psym := table.sym(new_type(generic_inst_parent_idx))
for {
if m := psym.find_method(name) {
Expand All @@ -2499,7 +2509,7 @@ pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
}
return m
}
if psym.parent_idx == 0 {
if psym.parent_idx <= 0 || psym.parent_idx >= table.type_symbols.len {
break
}
psym = table.type_symbols[psym.parent_idx]
Expand All @@ -2519,7 +2529,7 @@ pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
else {}
}
}
if psym2.parent_idx == 0 {
if psym2.parent_idx <= 0 || psym2.parent_idx >= table.type_symbols.len {
break
}
psym2 = table.type_symbols[psym2.parent_idx]
Expand Down Expand Up @@ -2594,7 +2604,7 @@ pub fn (t &TypeSymbol) has_field(name string) bool {
}

fn (a &Aggregate) find_field(name string) ?StructField {
for mut field in unsafe { a.fields } {
for field in unsafe { a.fields } {
if field.name.len == name.len && field.name == name {
return field
}
Expand All @@ -2603,7 +2613,7 @@ fn (a &Aggregate) find_field(name string) ?StructField {
}

pub fn (i &Interface) find_field(name string) ?StructField {
for mut field in unsafe { i.fields } {
for field in unsafe { i.fields } {
if field.name.len == name.len && field.name == name {
return field
}
Expand All @@ -2612,7 +2622,7 @@ pub fn (i &Interface) find_field(name string) ?StructField {
}

pub fn (i &Interface) find_method(name string) ?Fn {
for mut method in unsafe { i.methods } {
for method in unsafe { i.methods } {
if method.name.len == name.len && method.name == name {
return method
}
Expand All @@ -2621,7 +2631,7 @@ pub fn (i &Interface) find_method(name string) ?Fn {
}

pub fn (i &Interface) has_method(name string) bool {
for mut method in unsafe { i.methods } {
for method in unsafe { i.methods } {
if method.name.len == name.len && method.name == name {
return true
}
Expand All @@ -2630,7 +2640,7 @@ pub fn (i &Interface) has_method(name string) bool {
}

pub fn (s Struct) find_field(name string) ?StructField {
for mut field in unsafe { s.fields } {
for field in unsafe { s.fields } {
if name.len == field.name.len && field.name == name {
return field
}
Expand All @@ -2646,7 +2656,7 @@ pub fn (s Struct) get_field(name string) StructField {
}

pub fn (s &SumType) find_sum_type_field(name string) ?StructField {
for mut field in unsafe { s.fields } {
for field in unsafe { s.fields } {
if field.name == name {
return field
}
Expand Down
4 changes: 3 additions & 1 deletion vlib/v/checker/check_types.v
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,9 @@ fn (c &Checker) promote_num(left_type ast.Type, right_type ast.Type) ast.Type {
mut type_hi := left_type
mut type_lo := right_type
if type_hi.idx() < type_lo.idx() {
type_hi, type_lo = type_lo, type_hi
tmp := type_hi
type_hi = type_lo
type_lo = tmp
}
idx_hi := type_hi.idx()
idx_lo := type_lo.idx()
Expand Down
23 changes: 17 additions & 6 deletions vlib/v/parser/enum.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ mut:
uses_exprs bool
}

fn enum_attrs_contain(attrs []ast.Attr, name string) bool {
for attr in attrs {
if attr.name == name {
return true
}
}
return false
}

fn (mut p Parser) enum_val_expr(mod string) ast.EnumVal {
// `Color.green`
mut enum_name := p.check_name()
Expand Down Expand Up @@ -66,7 +75,7 @@ fn (mut p Parser) enum_decl_field(mut enum_attrs map[string][]ast.Attr, mut stat
p.attributes()
attrs << p.attrs
enum_attrs[val] = attrs
p.attrs = []
p.attrs = []ast.Attr{}
}
comments := p.eat_comments(same_line: true)
next_comments := p.eat_comments(follow_up: true)
Expand Down Expand Up @@ -183,6 +192,8 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
typ_pos = p.tok.pos()
enum_type = p.parse_type()
}
decl_attrs := p.attrs.clone()
p.attrs = []ast.Attr{}
mut enum_decl_comments := p.eat_comments()
p.check(.lcbr)
enum_decl_comments << p.eat_comments()
Expand All @@ -195,9 +206,9 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
p.enum_decl_fields(mut vals, mut fields, mut enum_attrs, mut state)
p.top_level_statement_end()
p.check(.rcbr)
is_flag := p.attrs.contains('flag')
is_typedef := p.attrs.contains('typedef')
is_multi_allowed := p.attrs.contains('_allow_multiple_values')
is_flag := enum_attrs_contain(decl_attrs, 'flag')
is_typedef := enum_attrs_contain(decl_attrs, 'typedef')
is_multi_allowed := enum_attrs_contain(decl_attrs, '_allow_multiple_values')
pubfn := if p.mod == 'main' { '@[flag_enum_fn] fn' } else { '@[flag_enum_fn] pub fn' }
if is_flag {
if fields.len > 64 {
Expand Down Expand Up @@ -262,7 +273,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
}
isb.write_string(' match val {\n')
for f in fields {
isb.write_string(' \'${f.name}\' { return ${enum_name}.${f.source_name} }\n')
isb.write_string(" '${f.name}' { return ${enum_name}.${f.source_name} }\n")
}
isb.write_string(' else{}\n')
isb.write_string(' }\n')
Expand Down Expand Up @@ -316,7 +327,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
is_multi_allowed: is_multi_allowed
fields: fields
pos: start_pos.extend_with_last_line(end_pos, p.prev_tok.line_nr)
attrs: p.attrs
attrs: decl_attrs
comments: enum_decl_comments
}

Expand Down
4 changes: 2 additions & 2 deletions vlib/v/parser/expr.v
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
if p.prev_tok.kind.is_assign() {
is_expr = true
}
return p.if_expr(true, is_expr)
node = p.if_expr(true, is_expr)
}
.key_match {
return p.match_expr(true, p.prev_tok.kind.is_assign())
node = p.match_expr(true, p.prev_tok.kind.is_assign())
}
else {
return p.unexpected_with_pos(p.peek_tok.pos(),
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/parser/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
mut is_expand_simple_interpolation := false
mut comments := []ast.Comment{}
fn_attrs := p.attrs
p.attrs = []
p.attrs = []ast.Attr{}
for fna in fn_attrs {
match fna.name {
'noreturn' {
Expand Down
Loading
Loading