Skip to content

Commit

Permalink
Merge branch 'master' into fix_comptime_method
Browse files Browse the repository at this point in the history
  • Loading branch information
spytheman authored Dec 4, 2023
2 parents 4eec1c6 + f941bb4 commit db6a369
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 108 deletions.
3 changes: 3 additions & 0 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ mut:
comptime_fields_type map[string]ast.Type
comptime_for_field_value ast.StructField // value of the field variable
comptime_enum_field_value string // current enum value name
comptime_for_method string // $for method in T.methods {}
comptime_for_method_var string // $for method in T.methods {}; the variable name
comptime_values_stack []CurrentComptimeValues // stores the values from the above on each $for loop, to make nesting them easier
fn_scope &ast.Scope = unsafe { nil }
main_fn_decl_node ast.FnDecl
match_exhaustive_cutoff_limit int = 10
Expand Down
63 changes: 61 additions & 2 deletions vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ fn (mut c Checker) get_comptime_var_type(node ast.Expr) ast.Type {
} else if node is ast.SelectorExpr && c.is_comptime_selector_type(node) {
// field_var.typ from $for field
return c.comptime_fields_default_type
} else if node is ast.ComptimeCall {
method_name := c.comptime_for_method
left_sym := c.table.sym(c.unwrap_generic(node.left_type))
f := left_sym.find_method(method_name) or {
c.error('could not find method `${method_name}` on compile-time resolution',
node.method_pos)
return ast.void_type
}
return f.return_type
}
return ast.void_type
}
Expand Down Expand Up @@ -274,6 +283,7 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
return
}
}
c.push_existing_comptime_values()
c.inside_comptime_for_field = true
for field in fields {
if c.field_data_type == 0 {
Expand All @@ -298,15 +308,15 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
}
}
}
c.comptime_for_field_var = ''
c.inside_comptime_for_field = false
c.pop_existing_comptime_values()
} else if c.table.generic_type_names(node.typ).len == 0 && sym.kind != .placeholder {
c.error('iterating over .fields is supported only for structs and interfaces, and ${sym.name} is neither',
node.typ_pos)
return
}
} else if node.kind == .values {
if sym.kind == .enum_ {
c.push_existing_comptime_values()
sym_info := sym.info as ast.Enum
c.inside_comptime_for_field = true
if c.enum_data_type == 0 {
Expand All @@ -319,11 +329,24 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
c.comptime_fields_type['${node.val_var}.typ'] = node.typ
c.stmts(mut node.stmts)
}
c.pop_existing_comptime_values()
} else {
c.error('iterating over .values is supported only for enums, and ${sym.name} is not an enum',
node.typ_pos)
return
}
} else if node.kind == .methods {
mut methods := sym.methods.filter(it.attrs.len == 0) // methods without attrs first
methods_with_attrs := sym.methods.filter(it.attrs.len > 0) // methods with attrs second
methods << methods_with_attrs

c.push_existing_comptime_values()
for method in methods {
c.comptime_for_method = method.name
c.comptime_for_method_var = node.val_var
c.stmts(mut node.stmts)
}
c.pop_existing_comptime_values()
} else {
c.stmts(mut node.stmts)
}
Expand Down Expand Up @@ -1036,3 +1059,39 @@ fn (mut c Checker) get_comptime_selector_bool_field(field_name string) bool {
else { return false }
}
}

struct CurrentComptimeValues {
inside_comptime_for_field bool
comptime_for_field_var string
comptime_fields_default_type ast.Type
comptime_fields_type map[string]ast.Type
comptime_for_field_value ast.StructField
comptime_enum_field_value string
comptime_for_method string
comptime_for_method_var string
}

fn (mut c Checker) push_existing_comptime_values() {
c.comptime_values_stack << CurrentComptimeValues{
inside_comptime_for_field: c.inside_comptime_for_field
comptime_for_field_var: c.comptime_for_field_var
comptime_fields_default_type: c.comptime_fields_default_type
comptime_fields_type: c.comptime_fields_type.clone()
comptime_for_field_value: c.comptime_for_field_value
comptime_enum_field_value: c.comptime_enum_field_value
comptime_for_method: c.comptime_for_method
comptime_for_method_var: c.comptime_for_method_var
}
}

fn (mut c Checker) pop_existing_comptime_values() {
old := c.comptime_values_stack.pop()
c.inside_comptime_for_field = old.inside_comptime_for_field
c.comptime_for_field_var = old.comptime_for_field_var
c.comptime_fields_default_type = old.comptime_fields_default_type
c.comptime_fields_type = old.comptime_fields_type.clone()
c.comptime_for_field_value = old.comptime_for_field_value
c.comptime_enum_field_value = old.comptime_enum_field_value
c.comptime_for_method = old.comptime_for_method
c.comptime_for_method_var = old.comptime_for_method_var
}
12 changes: 8 additions & 4 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,9 @@ fn (mut c Checker) get_comptime_args(func ast.Fn, node_ ast.CallExpr, concrete_t
comptime_args[i] = ct_value
}
}
}
} else if call_arg.expr is ast.ComptimeCall {
comptime_args[i] = c.get_comptime_var_type(call_arg.expr)
}
}
}
return comptime_args
Expand Down Expand Up @@ -1657,7 +1659,7 @@ fn (mut c Checker) cast_to_fixed_array_ret(typ ast.Type, sym ast.TypeSymbol) ast
return typ
}

// checks if a type from another module is is expected and visible(`is_pub`)
// checks if a type from another module is as 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 {
Expand Down Expand Up @@ -2618,7 +2620,7 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
if method_name[0] == `m` {
c.fail_if_immutable(mut node.left)
}
if node.left.is_auto_deref_var() || ret_type.has_flag(.shared_f) {
if node.left.is_auto_deref_var() || left_type.has_flag(.shared_f) {
ret_type = left_type.deref()
} else {
ret_type = left_type
Expand Down Expand Up @@ -2701,7 +2703,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
c.lambda_expr_fix_type_of_param(mut node.args[0].expr, mut node.args[0].expr.params[0],
elem_typ)
le_type := c.expr(mut node.args[0].expr.expr)
// eprintln('>>>>> node.args[0].expr: ${ast.Expr(node.args[0].expr)} | elem_typ: ${elem_typ} | etype: ${le_type}')
// eprintln('

>> node.args[0].expr: ${ast.Expr(node.args[0].expr)} | elem_typ: ${elem_typ} | etype: ${le_type}')
c.support_lambda_expr_one_param(elem_typ, le_type, mut node.args[0].expr)
} else {
c.support_lambda_expr_one_param(elem_typ, ast.bool_type, mut node.args[0].expr)
Expand Down
14 changes: 14 additions & 0 deletions vlib/v/checker/tests/comptime_field_selector_not_name_err.out
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,17 @@ vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:12: error: expec
| ~~~~
16 | }
17 |
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:10: error: compile time field access can only be used when iterating over `T.fields`
13 | }
14 | }
15 | _ = t.$(f.name)
| ^
16 | }
17 |
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:10: error: unknown `$for` variable `f`
13 | }
14 | }
15 | _ = t.$(f.name)
| ^
16 | }
17 |
30 changes: 14 additions & 16 deletions vlib/v/fmt/comments.v
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,22 @@ pub fn (mut f Fmt) comment(node ast.Comment, options CommentsOptions) {
}
f.write(out_s)
} else {
lines := node.text.trim_space().split_into_lines()
start_break := is_char_alphanumeric(node.text[0]) || node.text[0].is_space()
end_break := is_char_alphanumeric(node.text.trim('\t').bytes().last())
|| node.text.bytes().last().is_space()
lines := node.text.split_into_lines()
f.write('/*')
if start_break {
f.writeln('')
}
for line in lines {
f.writeln(line.trim_right(' '))
f.empty_line = false
}
if end_break {
f.empty_line = true
} else {
f.remove_new_line()
for i, line in lines {
if i == lines.len - 1 {
f.empty_line = false
if node.text[node.text.len - 1] == `\n` {
f.writeln(line)
} else {
f.write(line)
}
f.write('*/')
} else {
f.empty_line = false
f.writeln(line.trim_right(' '))
}
}
f.write('*/')
}
if options.level == .indent {
f.indent--
Expand Down
20 changes: 8 additions & 12 deletions vlib/v/fmt/tests/comments_expected.vv
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ fn single_line_blocks() {
}

fn main() {
/*
block1
/* block1
*/
/*
block2
*/
block2 */
/*
block3
*/
a := 1 // this is a comment
d := c // and an extra one
Expand All @@ -52,16 +52,12 @@ fn insert_space() {
}

fn linebreaks_in_block_comments() {
/*
foo
/*foo
comment goes here!
bar
*/
/*
spam
bar*/
/* spam
spaces make no difference there
eggs
*/
eggs */
}

fn between_if_branches() {
Expand Down
3 changes: 1 addition & 2 deletions vlib/v/fmt/tests/consts_with_comments_expected.vv
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const one = 1 // leave

const two = 2

/*
move
/* move
*/

const three = 3 // rewrite and leave
Expand Down
3 changes: 1 addition & 2 deletions vlib/v/fmt/tests/fn_headers_with_comments_expected.vv
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ fn C.Mix_LoadMUS3(file byteptr) voidptr // 1 2 3
// Loads music
fn C.Mix_LoadMUS4(file byteptr) voidptr

/*
Test
/* Test
*/
File renamed without changes.
7 changes: 7 additions & 0 deletions vlib/v/fmt/tests/multiline_comment_2_keep.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
*
* BRUH
*
*/
fn main() {
}
File renamed without changes.
66 changes: 0 additions & 66 deletions vlib/v/fmt/tests/structs_input.vv

This file was deleted.

25 changes: 21 additions & 4 deletions vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,21 @@ fn (mut g Gen) gen_array_sorted(node ast.CallExpr) {
info := sym.info as ast.Array
depth := g.get_array_depth(info.elem_type)

g.write('${atype} ${past.tmp_var} = array_clone_to_depth(ADDR(${atype},')
g.expr(node.left)
g.writeln('), ${depth});')
deref_field := if node.receiver_type.nr_muls() > node.left_type.nr_muls()
&& node.left_type.is_ptr() {
true
} else {
false
}
if !deref_field {
g.write('${atype} ${past.tmp_var} = array_clone_to_depth(ADDR(${atype},')
g.expr(node.left)
g.writeln('), ${depth});')
} else {
g.write('${atype} ${past.tmp_var} = array_clone_to_depth(')
g.expr(node.left)
g.writeln(', ${depth});')
}

unsafe {
node.left = ast.Expr(ast.Ident{
Expand Down Expand Up @@ -708,7 +720,12 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
}

fn (mut g Gen) gen_array_sort_call(node ast.CallExpr, compare_fn string) {
mut deref_field := g.dot_or_ptr(node.left_type)
deref_field := if node.receiver_type.nr_muls() > node.left_type.nr_muls()
&& node.left_type.is_ptr() {
g.dot_or_ptr(node.left_type.deref())
} else {
g.dot_or_ptr(node.left_type)
}
// eprintln('> qsort: pointer $node.left_type | deref_field: `$deref_field`')
g.empty_line = true
g.write('qsort(')
Expand Down
Loading

0 comments on commit db6a369

Please sign in to comment.