mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
tools: improve the v reduce
parser for functions, and add more loops to reduce more (#23694)
This commit is contained in:
parent
694cac9443
commit
6ed56eef64
@ -44,15 +44,14 @@ fn main() {
|
|||||||
content := os.read_file(file_path)!
|
content := os.read_file(file_path)!
|
||||||
assert string_reproduces(content, error_msg, command)
|
assert string_reproduces(content, error_msg, command)
|
||||||
show_code_stats(content, label: 'Original code size')
|
show_code_stats(content, label: 'Original code size')
|
||||||
mut tree := parse(content)
|
|
||||||
|
|
||||||
// start tests
|
// start tests
|
||||||
tmp_code := create_code(tree)
|
tmp_code := create_code(parse(content))
|
||||||
assert string_reproduces(tmp_code, error_msg, command)
|
assert string_reproduces(tmp_code, error_msg, command)
|
||||||
show_code_stats(tmp_code, label: 'Code size without comments')
|
show_code_stats(tmp_code, label: 'Code size without comments')
|
||||||
|
|
||||||
// reduce the code
|
// reduce the code
|
||||||
reduce_scope(mut tree, error_msg, command, do_fmt)
|
reduce_scope(content, error_msg, command, do_fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the command ran on the file produces the pattern
|
// Return true if the command ran on the file produces the pattern
|
||||||
@ -77,6 +76,7 @@ type Elem = string | Scope
|
|||||||
@[heap]
|
@[heap]
|
||||||
struct Scope {
|
struct Scope {
|
||||||
mut:
|
mut:
|
||||||
|
fn_scope bool // contains a function (string: signature{}, children: function body)
|
||||||
ignored bool // is the scope ignored when creating the file
|
ignored bool // is the scope ignored when creating the file
|
||||||
tmp_ignored bool // used when testing if it can be ignored in the file
|
tmp_ignored bool // used when testing if it can be ignored in the file
|
||||||
children []Elem // code blocks (strings & children scope
|
children []Elem // code blocks (strings & children scope
|
||||||
@ -96,6 +96,24 @@ fn parse(file string) Scope { // The parser is surely incomplete for the V synta
|
|||||||
for file[i] != `\n` { // comment -> skip until newline
|
for file[i] != `\n` { // comment -> skip until newline
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
} else if file[i] == `\n` && file[i - 1] == `\n` {
|
||||||
|
i++ // remove excess newlines
|
||||||
|
} else if file[i] == `\t` {
|
||||||
|
i++ // remove tabs for easier processing
|
||||||
|
} else if file[i] == `f` && file[i + 1] == `n` && file[i + 2] == ` ` && file[i - 1] or {
|
||||||
|
`\n`
|
||||||
|
} == `\n` {
|
||||||
|
top.children << current_string
|
||||||
|
// no increase in scope because not handled with {}
|
||||||
|
current_string = ''
|
||||||
|
top.children << &Scope{
|
||||||
|
fn_scope: true
|
||||||
|
}
|
||||||
|
stack << &(top.children[top.children.len - 1] as Scope)
|
||||||
|
current_string += file[i].ascii_str() // f
|
||||||
|
i++
|
||||||
|
current_string += file[i].ascii_str() // n
|
||||||
|
i++
|
||||||
} else if file[i] == `/` && file[i + 1] == `*` {
|
} else if file[i] == `/` && file[i + 1] == `*` {
|
||||||
i++
|
i++
|
||||||
i++
|
i++
|
||||||
@ -142,12 +160,23 @@ fn parse(file string) Scope { // The parser is surely incomplete for the V synta
|
|||||||
} else if file[i] == `}` {
|
} else if file[i] == `}` {
|
||||||
scope_level -= 1
|
scope_level -= 1
|
||||||
assert scope_level >= 0, 'The scopes are not well detected ${stack[0]}'
|
assert scope_level >= 0, 'The scopes are not well detected ${stack[0]}'
|
||||||
|
if current_string != '' {
|
||||||
top.children << current_string
|
top.children << current_string
|
||||||
|
}
|
||||||
|
if stack.last().children == [] {
|
||||||
|
stack[stack.len - 2].children.delete(stack[stack.len - 2].children.len - 1) // delete the empty scope (the last children because top of the stack)
|
||||||
|
}
|
||||||
stack.pop()
|
stack.pop()
|
||||||
top = stack[stack.len - 1]
|
top = stack[stack.len - 1]
|
||||||
current_string = ''
|
current_string = ''
|
||||||
current_string += file[i].ascii_str() // }
|
current_string += file[i].ascii_str() // }
|
||||||
i++
|
i++
|
||||||
|
if scope_level == 0 && stack.len == 2 { // the function and the body scope
|
||||||
|
top.children << current_string
|
||||||
|
stack.pop()
|
||||||
|
top = stack[stack.len - 1]
|
||||||
|
current_string = ''
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
current_string += file[i].ascii_str()
|
current_string += file[i].ascii_str()
|
||||||
i++
|
i++
|
||||||
@ -157,7 +186,7 @@ fn parse(file string) Scope { // The parser is surely incomplete for the V synta
|
|||||||
top = stack[stack.len - 1]
|
top = stack[stack.len - 1]
|
||||||
top.children << current_string // last part of the file
|
top.children << current_string // last part of the file
|
||||||
assert scope_level == 0, 'The scopes are not well detected'
|
assert scope_level == 0, 'The scopes are not well detected'
|
||||||
assert stack.len == 1, 'The stack should only have the BODY scope'
|
assert stack.len == 1, 'The stack should only have the body scope'
|
||||||
return *stack[0]
|
return *stack[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,8 +212,14 @@ fn create_code(sc Scope) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reduces the code contained in the scope tree and writes the reduced code to `rpdc.v`
|
// Reduces the code contained in the scope tree and writes the reduced code to `rpdc.v`
|
||||||
fn reduce_scope(mut sc Scope, error_msg string, command string, do_fmt bool) {
|
fn reduce_scope(content string, error_msg string, command string, do_fmt bool) {
|
||||||
|
mut sc := parse('') // will get filled in the start of the loop
|
||||||
println('Cleaning the scopes')
|
println('Cleaning the scopes')
|
||||||
|
mut text_code := content
|
||||||
|
mut outer_modified_smth := true
|
||||||
|
for outer_modified_smth {
|
||||||
|
sc = parse(text_code)
|
||||||
|
outer_modified_smth = false
|
||||||
mut modified_smth := true // was a modification successful in reducing the code in the last iteration
|
mut modified_smth := true // was a modification successful in reducing the code in the last iteration
|
||||||
for modified_smth { // as long as there are successful modifications
|
for modified_smth { // as long as there are successful modifications
|
||||||
modified_smth = false
|
modified_smth = false
|
||||||
@ -203,6 +238,7 @@ fn reduce_scope(mut sc Scope, error_msg string, command string, do_fmt bool) {
|
|||||||
if string_reproduces(code, error_msg, command) {
|
if string_reproduces(code, error_msg, command) {
|
||||||
item.ignored = true
|
item.ignored = true
|
||||||
modified_smth = true
|
modified_smth = true
|
||||||
|
outer_modified_smth = true
|
||||||
show_code_stats(code)
|
show_code_stats(code)
|
||||||
} else { // if can remove it, no need to go though it's children
|
} else { // if can remove it, no need to go though it's children
|
||||||
for i in 0 .. item.children.len {
|
for i in 0 .. item.children.len {
|
||||||
@ -214,14 +250,16 @@ fn reduce_scope(mut sc Scope, error_msg string, command string, do_fmt bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
text_code = create_code(sc)
|
||||||
|
|
||||||
println('Processing remaining lines')
|
println('Processing remaining lines')
|
||||||
tmp_code := create_code(sc).split_into_lines() // dont forget to add back the \n
|
split_code := text_code.split_into_lines() // dont forget to add back the \n
|
||||||
// Create the binary tree of the lines
|
// Create the binary tree of the lines
|
||||||
depth := int(math.log2(tmp_code.len)) + 1
|
depth := int(math.log2(split_code.len)) + 1
|
||||||
mut c := 0
|
mut c := 0
|
||||||
mut line_stack := []&Scope{}
|
mut line_stack := []&Scope{}
|
||||||
line_stack << &Scope{}
|
line_stack << &Scope{}
|
||||||
for c < tmp_code.len {
|
for c < split_code.len {
|
||||||
l1 := line_stack.len
|
l1 := line_stack.len
|
||||||
if l1 <= depth { // or equal because of the first node
|
if l1 <= depth { // or equal because of the first node
|
||||||
if line_stack[l1 - 1].children.len < 2 {
|
if line_stack[l1 - 1].children.len < 2 {
|
||||||
@ -235,7 +273,7 @@ fn reduce_scope(mut sc Scope, error_msg string, command string, do_fmt bool) {
|
|||||||
if line_stack[l1 - 1].children.len != 0 { // if there is already a string
|
if line_stack[l1 - 1].children.len != 0 { // if there is already a string
|
||||||
line_stack.pop()
|
line_stack.pop()
|
||||||
} else {
|
} else {
|
||||||
line_stack[l1 - 1].children << tmp_code[c] + '\n' // the \n were removed by the split
|
line_stack[l1 - 1].children << split_code[c] + '\n' // the \n were removed by the split
|
||||||
c++
|
c++
|
||||||
line_stack.pop() // already a string
|
line_stack.pop() // already a string
|
||||||
}
|
}
|
||||||
@ -264,6 +302,7 @@ fn reduce_scope(mut sc Scope, error_msg string, command string, do_fmt bool) {
|
|||||||
if string_reproduces(code, error_msg, command) {
|
if string_reproduces(code, error_msg, command) {
|
||||||
item.ignored = true
|
item.ignored = true
|
||||||
modified_smth = true
|
modified_smth = true
|
||||||
|
outer_modified_smth = true
|
||||||
show_code_stats(code)
|
show_code_stats(code)
|
||||||
} else { // if can remove it, can remove it's children
|
} else { // if can remove it, can remove it's children
|
||||||
for i in 0 .. item.children.len {
|
for i in 0 .. item.children.len {
|
||||||
@ -274,10 +313,11 @@ fn reduce_scope(mut sc Scope, error_msg string, command string, do_fmt bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
text_code = create_code(line_tree)
|
||||||
|
}
|
||||||
|
|
||||||
mre := create_code(line_tree) // final minimal reproductible example
|
assert string_reproduces(text_code, error_msg, command)
|
||||||
assert string_reproduces(mre, error_msg, command)
|
os.write_file('rpdc.v', text_code) or { panic(err) }
|
||||||
os.write_file('rpdc.v', mre) or { panic(err) }
|
|
||||||
if do_fmt {
|
if do_fmt {
|
||||||
os.execute('v fmt -w rpdc.v')
|
os.execute('v fmt -w rpdc.v')
|
||||||
final_content := os.read_file('rpdc.v') or { panic(err) }
|
final_content := os.read_file('rpdc.v') or { panic(err) }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user