Compare commits

..

No commits in common. "b81f06e3699dbb1aca577876c13031394de22182" and "9d764cd25e5aeab80e8d74c0cdbb25bfa4761924" have entirely different histories.

74 changed files with 241 additions and 1142 deletions

View File

@ -61,7 +61,9 @@ fn main() {
if term_colors { if term_colors {
os.setenv('VCOLORS', 'always', true) os.setenv('VCOLORS', 'always', true)
} }
foptions.vlog('vfmt foptions: $foptions') if foptions.is_verbose {
eprintln('vfmt foptions: $foptions')
}
if foptions.is_worker { if foptions.is_worker {
// -worker should be added by a parent vfmt process. // -worker should be added by a parent vfmt process.
// We launch a sub process for each file because // We launch a sub process for each file because
@ -107,7 +109,9 @@ fn main() {
mut worker_command_array := cli_args_no_files.clone() mut worker_command_array := cli_args_no_files.clone()
worker_command_array << ['-worker', util.quote_path(fpath)] worker_command_array << ['-worker', util.quote_path(fpath)]
worker_cmd := worker_command_array.join(' ') worker_cmd := worker_command_array.join(' ')
foptions.vlog('vfmt worker_cmd: $worker_cmd') if foptions.is_verbose {
eprintln('vfmt worker_cmd: $worker_cmd')
}
worker_result := os.execute(worker_cmd) worker_result := os.execute(worker_cmd)
// Guard against a possibly crashing worker process. // Guard against a possibly crashing worker process.
if worker_result.exit_code != 0 { if worker_result.exit_code != 0 {
@ -147,43 +151,43 @@ fn main() {
} }
} }
fn setup_preferences_and_table() (&pref.Preferences, &ast.Table) { fn (foptions &FormatOptions) format_file(file string) {
table := ast.new_table()
mut prefs := pref.new_preferences() mut prefs := pref.new_preferences()
prefs.is_fmt = true prefs.is_fmt = true
prefs.skip_warnings = true
return prefs, table
}
fn (foptions &FormatOptions) vlog(msg string) {
if foptions.is_verbose { if foptions.is_verbose {
eprintln(msg) eprintln('vfmt2 running fmt.fmt over file: $file')
} }
} table := ast.new_table()
// checker := checker.new_checker(table, prefs)
fn (foptions &FormatOptions) format_file(file string) {
foptions.vlog('vfmt2 running fmt.fmt over file: $file')
prefs, table := setup_preferences_and_table()
file_ast := parser.parse_file(file, table, .parse_comments, prefs) file_ast := parser.parse_file(file, table, .parse_comments, prefs)
// checker.new_checker(table, prefs).check(file_ast) // checker.check(file_ast)
formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug) formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug)
file_name := os.file_name(file) file_name := os.file_name(file)
ulid := rand.ulid() ulid := rand.ulid()
vfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_$file_name') vfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_$file_name')
os.write_file(vfmt_output_path, formatted_content) or { panic(err) } os.write_file(vfmt_output_path, formatted_content) or { panic(err) }
foptions.vlog('fmt.fmt worked and $formatted_content.len bytes were written to $vfmt_output_path .') if foptions.is_verbose {
eprintln('fmt.fmt worked and $formatted_content.len bytes were written to $vfmt_output_path .')
}
eprintln('$formatted_file_token$vfmt_output_path') eprintln('$formatted_file_token$vfmt_output_path')
} }
fn (foptions &FormatOptions) format_pipe() { fn (foptions &FormatOptions) format_pipe() {
foptions.vlog('vfmt2 running fmt.fmt over stdin') mut prefs := pref.new_preferences()
prefs, table := setup_preferences_and_table() prefs.is_fmt = true
if foptions.is_verbose {
eprintln('vfmt2 running fmt.fmt over stdin')
}
input_text := os.get_raw_lines_joined() input_text := os.get_raw_lines_joined()
table := ast.new_table()
// checker := checker.new_checker(table, prefs)
file_ast := parser.parse_text(input_text, '', table, .parse_comments, prefs) file_ast := parser.parse_text(input_text, '', table, .parse_comments, prefs)
// checker.new_checker(table, prefs).check(file_ast) // checker.check(file_ast)
formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug) formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug)
print(formatted_content) print(formatted_content)
foptions.vlog('fmt.fmt worked and $formatted_content.len bytes were written to stdout.') if foptions.is_verbose {
eprintln('fmt.fmt worked and $formatted_content.len bytes were written to stdout.')
}
} }
fn print_compiler_options(compiler_params &pref.Preferences) { fn print_compiler_options(compiler_params &pref.Preferences) {
@ -230,7 +234,9 @@ fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_pa
return return
} }
diff_cmd := foptions.find_diff_cmd() diff_cmd := foptions.find_diff_cmd()
foptions.vlog('Using diff command: $diff_cmd') if foptions.is_verbose {
eprintln('Using diff command: $diff_cmd')
}
diff := diff.color_compare_files(diff_cmd, file, formatted_file_path) diff := diff.color_compare_files(diff_cmd, file, formatted_file_path)
if diff.len > 0 { if diff.len > 0 {
println(diff) println(diff)

View File

@ -49,26 +49,17 @@ enum RunCommandKind {
const expect_nothing = '<nothing>' const expect_nothing = '<nothing>'
const starts_with_nothing = '<nothing>'
const ends_with_nothing = '<nothing>'
const contains_nothing = '<nothing>'
struct Command { struct Command {
mut: mut:
line string line string
label string // when set, the label will be printed *before* cmd.line is executed label string // when set, the label will be printed *before* cmd.line is executed
ecode int ecode int
okmsg string okmsg string
errmsg string errmsg string
rmfile string rmfile string
runcmd RunCommandKind = .system runcmd RunCommandKind = .system
expect string = expect_nothing expect string = expect_nothing
starts_with string = starts_with_nothing output string
ends_with string = ends_with_nothing
contains string = contains_nothing
output string
} }
fn get_all_commands() []Command { fn get_all_commands() []Command {
@ -108,14 +99,6 @@ fn get_all_commands() []Command {
runcmd: .execute runcmd: .execute
expect: 'Hello, World!\n' expect: 'Hello, World!\n'
} }
res << Command{
line: '$vexe interpret examples/hanoi.v'
okmsg: 'V can interpret hanoi.v'
runcmd: .execute
starts_with: 'Disc 1 from A to C...\n'
ends_with: 'Disc 1 from A to C...\n'
contains: 'Disc 7 from A to C...\n'
}
res << Command{ res << Command{
line: '$vexe -o - examples/hello_world.v | grep "#define V_COMMIT_HASH" > /dev/null' line: '$vexe -o - examples/hello_world.v | grep "#define V_COMMIT_HASH" > /dev/null'
okmsg: 'V prints the generated source code to stdout with `-o -` .' okmsg: 'V prints the generated source code to stdout with `-o -` .'
@ -269,56 +252,23 @@ fn (mut cmd Command) run() {
spent := sw.elapsed().milliseconds() spent := sw.elapsed().milliseconds()
// //
mut is_failed := false mut is_failed := false
mut is_failed_expected := false
mut is_failed_starts_with := false
mut is_failed_ends_with := false
mut is_failed_contains := false
if cmd.ecode != 0 { if cmd.ecode != 0 {
is_failed = true is_failed = true
} }
if cmd.expect != expect_nothing { if cmd.expect != expect_nothing {
if cmd.output != cmd.expect { if cmd.output != cmd.expect {
is_failed = true is_failed = true
is_failed_expected = true
}
}
if cmd.starts_with != starts_with_nothing {
if !cmd.output.starts_with(cmd.starts_with) {
is_failed = true
is_failed_starts_with = true
}
}
if cmd.ends_with != ends_with_nothing {
if !cmd.output.ends_with(cmd.ends_with) {
is_failed = true
is_failed_ends_with = true
}
}
if cmd.contains != contains_nothing {
if !cmd.output.contains(cmd.contains) {
is_failed = true
is_failed_contains = true
} }
} }
// //
run_label := if is_failed { term.failed('FAILED') } else { term_highlight('OK') } run_label := if is_failed { term.failed('FAILED') } else { term_highlight('OK') }
println('> Running: "$cmd.line" took: $spent ms ... $run_label') println('> Running: "$cmd.line" took: $spent ms ... $run_label')
// //
if is_failed && is_failed_expected { if is_failed && cmd.expect != expect_nothing {
eprintln('> expected:\n$cmd.expect') if cmd.output != cmd.expect {
eprintln('> output:\n$cmd.output') eprintln('> expected:\n$cmd.expect')
} eprintln('> output:\n$cmd.output')
if is_failed && is_failed_starts_with { }
eprintln('> expected to start with:\n$cmd.starts_with')
eprintln('> output:\n${cmd.output#[..cmd.starts_with.len]}')
}
if is_failed && is_failed_ends_with {
eprintln('> expected to end with:\n$cmd.ends_with')
eprintln('> output:\n${cmd.output#[-cmd.starts_with.len..]}')
}
if is_failed && is_failed_contains {
eprintln('> expected to contain:\n$cmd.contains')
eprintln('> output:\n$cmd.output')
} }
if vtest_nocleanup { if vtest_nocleanup {
return return

View File

@ -1,18 +1,3 @@
fn main() {
graph := {
'A': ['B', 'C']
'B': ['A', 'D', 'E']
'C': ['A', 'F']
'D': ['B']
'E': ['B', 'F']
'F': ['C', 'E']
}
println('Graph: $graph')
path := breadth_first_search_path(graph, 'A', 'F')
println('The shortest path from node A to node F is: $path')
assert path == ['A', 'C', 'F']
}
// Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph. // Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph.
fn breadth_first_search_path(graph map[string][]string, vertex string, target string) []string { fn breadth_first_search_path(graph map[string][]string, vertex string, target string) []string {
mut path := []string{} mut path := []string{}
@ -39,3 +24,18 @@ fn breadth_first_search_path(graph map[string][]string, vertex string, target st
} }
return path return path
} }
fn main() {
graph := {
'A': ['B', 'C']
'B': ['A', 'D', 'E']
'C': ['A', 'F']
'D': ['B']
'E': ['B', 'F']
'F': ['C', 'E']
}
println('Graph: $graph')
path := breadth_first_search_path(graph, 'A', 'F')
println('The shortest path from node A to node F is: $path')
assert path == ['A', 'C', 'F']
}

View File

@ -32,7 +32,8 @@ const (
struct App { struct App {
minutes_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, minutes_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw,
tp + 1 * th, center - tw, tp + 1 * th] tp +
1 * th, center - tw, tp + 1 * th]
hours_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, tp + 2 * th, hours_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, tp + 2 * th,
center - tw, tp + 2 * th] center - tw, tp + 2 * th]
hours3_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, tp + 3 * th, hours3_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, tp + 3 * th,

View File

@ -1,92 +0,0 @@
// Author: ccs
// I follow literally code in C, done many years ago
fn main() {
// Adjacency matrix as a map
graph := {
'A': ['B', 'C']
'B': ['A', 'D', 'E']
'C': ['A', 'F']
'D': ['B']
'E': ['B', 'F']
'F': ['C', 'E']
}
println('Graph: $graph')
path := breadth_first_search_path(graph, 'A', 'F')
println('\n The shortest path from node A to node F is: $path.reverse()')
}
// Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph.
fn breadth_first_search_path(graph map[string][]string, start string, target string) []string {
mut path := []string{} // ONE PATH with SUCCESS = array
mut queue := []string{} // a queue ... many paths
// all_nodes := graph.keys() // get a key of this map
n_nodes := graph.len // numbers of nodes of this graph
// a map to store all the nodes visited to avoid cycles
// start all them with False, not visited yet
mut visited := a_map_nodes_bool(n_nodes) // a map fully
// false ==> not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}
queue << start // first arrival
for queue.len != 0 {
mut node := departure(mut queue) // get the front node and remove it
if visited[node] == false { // check if this node is already visited
// if no ... test it searchinf for a final node
visited[node] = true // means: visit this node
if node == target {
path = build_path_reverse(graph, start, node, visited)
return path
}
// Expansion of node removed from queue
print('\n Expansion of node $node (true/false): ${graph[node]}')
// take all nodes from the node
for vertex in graph[node] { // println("\n ...${vertex}")
// not explored yet
if visited[vertex] == false {
queue << vertex
}
}
print('\n QUEUE: $queue (only not visited) \n Visited: $visited')
}
}
path = ['Path not found, problem in the Graph, start or end nodes! ']
return path
}
// Creating a map for VISITED nodes ...
// starting by false ===> means this node was not visited yet
fn a_map_nodes_bool(size int) map[string]bool {
mut my_map := map[string]bool{} // look this map ...
base := u8(65)
mut key := base.ascii_str()
for i in 0 .. size {
key = u8(base + i).ascii_str()
my_map[key] = false
}
return my_map
}
// classical removing of a node from the start of a queue
fn departure(mut queue []string) string {
mut x := queue[0]
queue.delete(0)
return x
}
// Based in the current node that is final, search for its parent, already visited, up to the root or start node
fn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {
print('\n\n Nodes visited (true) or no (false): $visited')
array_of_nodes := graph.keys()
mut current := final
mut path := []string{}
path << current
for (current != start) {
for i in array_of_nodes {
if (current in graph[i]) && (visited[i] == true) {
current = i
break // the first ocurrence is enough
}
}
path << current // update the path tracked
}
return path
}

View File

@ -1,103 +0,0 @@
// Author: ccs
// I follow literally code in C, done many years ago
fn main() {
// Adjacency matrix as a map
// Example 01
graph_01 := {
'A': ['B', 'C']
'B': ['A', 'D', 'E']
'C': ['A', 'F']
'D': ['B']
'E': ['F', 'B', 'F']
'F': ['C', 'E']
}
// Example 02
graph_02 := {
'A': ['B', 'C', 'D']
'B': ['E']
'C': ['F']
'D': ['E']
'E': ['H']
'F': ['H']
'G': ['H']
'H': ['E', 'F', 'G']
}
// println('Graph: $graph')
path_01 := depth_first_search_path(graph_01, 'A', 'F')
println('\n Graph_01: a first path from node A to node F is: $path_01.reverse()')
path_02 := depth_first_search_path(graph_02, 'A', 'H')
println('\n Graph_02: a first path from node A to node F is: $path_02.reverse()')
}
// Depth-First Search (BFS) allows you to find a path between two nodes in the graph.
fn depth_first_search_path(graph map[string][]string, start string, target string) []string {
mut path := []string{} // ONE PATH with SUCCESS = array
mut stack := []string{} // a stack ... many nodes
// all_nodes := graph.keys() // get a key of this map
n_nodes := graph.len // numbers of nodes of this graph
mut visited := a_map_nodes_bool(n_nodes) // a map fully
// false ... not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}
stack << start // first push on the stack
for stack.len > 0 {
mut node := stack.pop() // get the top node and remove it from the stack
// check if this node is already visited
if visited[node] == false {
// if no ... test it searchin for a final node
visited[node] = true // means: node visited
if node == target {
path = build_path_reverse(graph, start, node, visited)
return path
}
// Exploring of node removed from stack and add its relatives
print('\n Exploring of node $node (true/false): ${graph[node]}')
// graph[node].reverse() take a classical choice for DFS
// at most os left in this case.
// use vertex in graph[node] the choice is right
// take all nodes from the node
for vertex in graph[node].reverse() {
// println("\n ...${vertex}")
// not explored yet
if visited[vertex] == false {
stack << vertex
}
}
print('\n Stack: $stack (only not visited) \n Visited: $visited')
}
}
path = ['Path not found, problem in the Graph, start or end nodes! ']
return path
}
// Creating a map for nodes not VISITED visited ...
// starting by false ===> means this node was not visited yet
fn a_map_nodes_bool(size int) map[string]bool {
mut my_map := map[string]bool{} // look this map ...
for i in 0 .. size {
my_map[u8(65 + i).ascii_str()] = false
}
return my_map
}
// Based in the current node that is final, search for his parent, that is already visited, up to the root or start node
fn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {
print('\n\n Nodes visited (true) or no (false): $visited')
array_of_nodes := graph.keys()
mut current := final
mut path := []string{}
path << current
for current != start {
for i in array_of_nodes {
if (current in graph[i]) && (visited[i] == true) {
current = i
break // the first ocurrence is enough
}
}
path << current // updating the path tracked
}
return path
}

View File

@ -931,7 +931,7 @@ fn test_u64_keys() {
m[i]++ m[i]++
assert m[i] == i + 1 assert m[i] == i + 1
} }
assert u64(m.len) == end assert m.len == end
keys := m.keys() keys := m.keys()
for i in u64(0) .. end { for i in u64(0) .. end {
assert keys[i] == i assert keys[i] == i

View File

@ -919,7 +919,7 @@ fn test_u64_keys() {
m[i]++ m[i]++
assert m[i] == i + 1 assert m[i] == i + 1
} }
assert u64(m.len) == end assert m.len == end
keys := m.keys() keys := m.keys()
for i in u64(0) .. end { for i in u64(0) .. end {
assert keys[i] == i assert keys[i] == i

View File

@ -28,7 +28,6 @@ fn help_cmd() Command {
} }
} }
// print_help_for_command outputs the help message of `help_cmd`.
pub fn print_help_for_command(help_cmd Command) ? { pub fn print_help_for_command(help_cmd Command) ? {
if help_cmd.args.len > 0 { if help_cmd.args.len > 0 {
mut cmd := help_cmd.parent mut cmd := help_cmd.parent
@ -55,7 +54,6 @@ pub fn print_help_for_command(help_cmd Command) ? {
} }
} }
// help_message returns a generated help message as a `string` for the `Command`.
pub fn (cmd Command) help_message() string { pub fn (cmd Command) help_message() string {
mut help := '' mut help := ''
help += 'Usage: $cmd.full_name()' help += 'Usage: $cmd.full_name()'

View File

@ -51,7 +51,8 @@ const (
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd], 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd],
'Test With Truncation'.bytes(), 'Test Using Larger Than Block-Size Key - Hash Key First'.bytes(), 'Test With Truncation'.bytes(),
'Test Using Larger Than Block-Size Key - Hash Key First'.bytes(),
'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data'.bytes()] 'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data'.bytes()]
) )

View File

@ -278,114 +278,72 @@ pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius
// `x`,`y` is the top-left corner of the rectangle. // `x`,`y` is the top-left corner of the rectangle.
// `w` is the width, `h` is the height . // `w` is the width, `h` is the height .
// `radius` is the radius of the corner-rounding in pixels. // `radius` is the radius of the corner-rounding in pixels.
// `c` is the color of the filled. // `c` is the color of the outline.
pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radius f32, c gx.Color) { pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radius f32, c gx.Color) {
assert w > 0 && h > 0 && radius >= 0
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
}
sgl.c4b(c.r, c.g, c.b, c.a) sgl.c4b(c.r, c.g, c.b, c.a)
sgl.begin_triangle_strip()
mut theta := f32(0)
mut xx := f32(0) mut xx := f32(0)
mut yy := f32(0) mut yy := f32(0)
mut radians := f32(0) r := radius * ctx.scale
mut new_radius := radius
if w >= h && radius > h / 2 {
new_radius = h / 2
} else if radius > w / 2 {
new_radius = w / 2
}
r := new_radius * ctx.scale
nx := x * ctx.scale nx := x * ctx.scale
ny := y * ctx.scale ny := y * ctx.scale
width := w * ctx.scale width := w * ctx.scale
height := h * ctx.scale height := h * ctx.scale
segments := 2 * math.pi * r
// left top quarter segdiv := segments / 4
sgl.begin_triangle_strip() rb := 0
ltx := nx + r lb := int(rb + segdiv)
lty := ny + r lt := int(lb + segdiv)
for i in 0 .. 91 { rt := int(lt + segdiv)
if r == 0 { // left top
break lx := nx + r
} ly := ny + r
radians = f32(math.radians(i)) for i in lt .. rt {
xx = r * math.cosf(radians) theta = 2 * f32(math.pi) * f32(i) / segments
yy = r * math.sinf(radians) xx = r * math.cosf(theta)
sgl.v2f(ltx - xx, lty - yy) yy = r * math.sinf(theta)
sgl.v2f(ltx, lty) sgl.v2f(xx + lx, yy + ly)
sgl.v2f(lx, ly)
} }
sgl.end() // right top
mut rx := nx + width - r
// right top quarter mut ry := ny + r
sgl.begin_triangle_strip() for i in rt .. int(segments) {
rtx := nx + width - r theta = 2 * f32(math.pi) * f32(i) / segments
rty := ny + r xx = r * math.cosf(theta)
for i in 0 .. 91 { yy = r * math.sinf(theta)
if r == 0 { sgl.v2f(xx + rx, yy + ry)
break sgl.v2f(rx, ry)
}
radians = f32(math.radians(i))
xx = r * math.cosf(radians)
yy = r * math.sinf(radians)
sgl.v2f(rtx + xx, rty - yy)
sgl.v2f(rtx, rty)
} }
sgl.end() // right bottom
mut rbx := rx
// right bottom quarter mut rby := ny + height - r
sgl.begin_triangle_strip() for i in rb .. lb {
rbx := nx + width - r theta = 2 * f32(math.pi) * f32(i) / segments
rby := ny + height - r xx = r * math.cosf(theta)
for i in 0 .. 91 { yy = r * math.sinf(theta)
if r == 0 { sgl.v2f(xx + rbx, yy + rby)
break
}
radians = f32(math.radians(i))
xx = r * math.cosf(radians)
yy = r * math.sinf(radians)
sgl.v2f(rbx + xx, rby + yy)
sgl.v2f(rbx, rby) sgl.v2f(rbx, rby)
} }
sgl.end() // left bottom
mut lbx := lx
// left bottom quarter mut lby := ny + height - r
sgl.begin_triangle_strip() for i in lb .. lt {
lbx := nx + r theta = 2 * f32(math.pi) * f32(i) / segments
lby := ny + height - r xx = r * math.cosf(theta)
for i in 0 .. 91 { yy = r * math.sinf(theta)
if r == 0 { sgl.v2f(xx + lbx, yy + lby)
break
}
radians = f32(math.radians(i))
xx = r * math.cosf(radians)
yy = r * math.sinf(radians)
sgl.v2f(lbx - xx, lby + yy)
sgl.v2f(lbx, lby) sgl.v2f(lbx, lby)
} }
sgl.v2f(lx + xx, ly)
sgl.v2f(lx, ly)
sgl.end() sgl.end()
// Separate drawing is to prevent transparent color overlap
// top rectangle
sgl.begin_quads() sgl.begin_quads()
sgl.v2f(ltx, ny) sgl.v2f(lx, ly)
sgl.v2f(rtx, ny) sgl.v2f(rx, ry)
sgl.v2f(rtx, rty)
sgl.v2f(ltx, lty)
sgl.end()
// middle rectangle
sgl.begin_quads()
sgl.v2f(nx, ny + r)
sgl.v2f(rtx + r, rty)
sgl.v2f(rbx + r, rby)
sgl.v2f(nx, lby)
sgl.end()
// bottom rectangle
sgl.begin_quads()
sgl.v2f(lbx, lby)
sgl.v2f(rbx, rby) sgl.v2f(rbx, rby)
sgl.v2f(rbx, ny + height) sgl.v2f(lbx, lby)
sgl.v2f(lbx, ny + height)
sgl.end() sgl.end()
} }

View File

@ -242,7 +242,8 @@ const (
cookie: [&http.Cookie{ cookie: [&http.Cookie{
name: 'cookie-1' name: 'cookie-1'
value: 'v1' value: 'v1'
}, &http.Cookie{ },
&http.Cookie{
name: 'cookie-2' name: 'cookie-2'
value: 'v2' value: 'v2'
}, },
@ -293,7 +294,8 @@ const (
header: { header: {
'Set-Cookie': ['ASP.NET_SessionId=foo; path=/; HttpOnly'] 'Set-Cookie': ['ASP.NET_SessionId=foo; path=/; HttpOnly']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'ASP.NET_SessionId' name: 'ASP.NET_SessionId'
value: 'foo' value: 'foo'
path: '/' path: '/'
@ -305,7 +307,8 @@ const (
header: { header: {
'Set-Cookie': ['samesitedefault=foo; SameSite'] 'Set-Cookie': ['samesitedefault=foo; SameSite']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'samesitedefault' name: 'samesitedefault'
value: 'foo' value: 'foo'
same_site: .same_site_default_mode same_site: .same_site_default_mode
@ -316,7 +319,8 @@ const (
header: { header: {
'Set-Cookie': ['samesitelax=foo; SameSite=Lax'] 'Set-Cookie': ['samesitelax=foo; SameSite=Lax']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'samesitelax' name: 'samesitelax'
value: 'foo' value: 'foo'
same_site: .same_site_lax_mode same_site: .same_site_lax_mode
@ -327,7 +331,8 @@ const (
header: { header: {
'Set-Cookie': ['samesitestrict=foo; SameSite=Strict'] 'Set-Cookie': ['samesitestrict=foo; SameSite=Strict']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'samesitestrict' name: 'samesitestrict'
value: 'foo' value: 'foo'
same_site: .same_site_strict_mode same_site: .same_site_strict_mode
@ -338,7 +343,8 @@ const (
header: { header: {
'Set-Cookie': ['samesitenone=foo; SameSite=None'] 'Set-Cookie': ['samesitenone=foo; SameSite=None']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'samesitenone' name: 'samesitenone'
value: 'foo' value: 'foo'
same_site: .same_site_none_mode same_site: .same_site_none_mode
@ -351,7 +357,8 @@ const (
header: { header: {
'Set-Cookie': ['special-1=a z'] 'Set-Cookie': ['special-1=a z']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-1' name: 'special-1'
value: 'a z' value: 'a z'
raw: 'special-1=a z' raw: 'special-1=a z'
@ -361,7 +368,8 @@ const (
header: { header: {
'Set-Cookie': ['special-2=" z"'] 'Set-Cookie': ['special-2=" z"']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-2' name: 'special-2'
value: ' z' value: ' z'
raw: 'special-2=" z"' raw: 'special-2=" z"'
@ -371,7 +379,8 @@ const (
header: { header: {
'Set-Cookie': ['special-3="a "'] 'Set-Cookie': ['special-3="a "']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-3' name: 'special-3'
value: 'a ' value: 'a '
raw: 'special-3="a "' raw: 'special-3="a "'
@ -381,7 +390,8 @@ const (
header: { header: {
'Set-Cookie': ['special-4=" "'] 'Set-Cookie': ['special-4=" "']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-4' name: 'special-4'
value: ' ' value: ' '
raw: 'special-4=" "' raw: 'special-4=" "'
@ -391,7 +401,8 @@ const (
header: { header: {
'Set-Cookie': ['special-5=a,z'] 'Set-Cookie': ['special-5=a,z']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-5' name: 'special-5'
value: 'a,z' value: 'a,z'
raw: 'special-5=a,z' raw: 'special-5=a,z'
@ -401,7 +412,8 @@ const (
header: { header: {
'Set-Cookie': ['special-6=",z"'] 'Set-Cookie': ['special-6=",z"']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-6' name: 'special-6'
value: ',z' value: ',z'
raw: 'special-6=",z"' raw: 'special-6=",z"'
@ -411,7 +423,8 @@ const (
header: { header: {
'Set-Cookie': ['special-7=","'] 'Set-Cookie': ['special-7=","']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-7' name: 'special-7'
value: ',' value: ','
raw: 'special-8=","' raw: 'special-8=","'

View File

@ -223,7 +223,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
buffer[bytes_read] = rbuff[0] buffer[bytes_read] = rbuff[0]
bytes_read++ bytes_read++
// parses the first two header bytes to get basic frame information // parses the first two header bytes to get basic frame information
if bytes_read == websocket.header_len_offset { if bytes_read == u64(websocket.header_len_offset) {
frame.fin = (buffer[0] & 0x80) == 0x80 frame.fin = (buffer[0] & 0x80) == 0x80
frame.rsv1 = (buffer[0] & 0x40) == 0x40 frame.rsv1 = (buffer[0] & 0x40) == 0x40
frame.rsv2 = (buffer[0] & 0x20) == 0x20 frame.rsv2 = (buffer[0] & 0x20) == 0x20
@ -249,7 +249,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
break break
} }
} }
if frame.payload_len == 126 && bytes_read == websocket.extended_payload16_end_byte { if frame.payload_len == 126 && bytes_read == u64(websocket.extended_payload16_end_byte) {
frame.header_len += 2 frame.header_len += 2
frame.payload_len = 0 frame.payload_len = 0
frame.payload_len |= int(u32(buffer[2]) << 8) frame.payload_len |= int(u32(buffer[2]) << 8)
@ -259,7 +259,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
break break
} }
} }
if frame.payload_len == 127 && bytes_read == websocket.extended_payload64_end_byte { if frame.payload_len == 127 && bytes_read == u64(websocket.extended_payload64_end_byte) {
frame.header_len += 8 frame.header_len += 8
// these shift operators needs 64 bit on clang with -prod flag // these shift operators needs 64 bit on clang with -prod flag
mut payload_len := u64(0) mut payload_len := u64(0)

View File

@ -162,7 +162,6 @@ pub fn rmdir_all(path string) ? {
} }
// is_dir_empty will return a `bool` whether or not `path` is empty. // is_dir_empty will return a `bool` whether or not `path` is empty.
// Note that it will return `true` if `path` does not exist.
[manualfree] [manualfree]
pub fn is_dir_empty(path string) bool { pub fn is_dir_empty(path string) bool {
items := ls(path) or { return true } items := ls(path) or { return true }

View File

@ -41,7 +41,7 @@ fn test_open_file() {
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) } mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
file.write_string(hello) or { panic(err) } file.write_string(hello) or { panic(err) }
file.close() file.close()
assert u64(hello.len) == os.file_size(filename) assert hello.len == os.file_size(filename)
read_hello := os.read_file(filename) or { panic('error reading file $filename') } read_hello := os.read_file(filename) or { panic('error reading file $filename') }
assert hello == read_hello assert hello == read_hello
os.rm(filename) or { panic(err) } os.rm(filename) or { panic(err) }
@ -58,7 +58,7 @@ fn test_open_file_binary() {
bytes := hello.bytes() bytes := hello.bytes()
unsafe { file.write_ptr(bytes.data, bytes.len) } unsafe { file.write_ptr(bytes.data, bytes.len) }
file.close() file.close()
assert u64(hello.len) == os.file_size(filename) assert hello.len == os.file_size(filename)
read_hello := os.read_bytes(filename) or { panic('error reading file $filename') } read_hello := os.read_bytes(filename) or { panic('error reading file $filename') }
assert bytes == read_hello assert bytes == read_hello
os.rm(filename) or { panic(err) } os.rm(filename) or { panic(err) }
@ -100,7 +100,7 @@ fn test_create_file() ? {
filename := './test1.txt' filename := './test1.txt'
hello := 'hello world!' hello := 'hello world!'
create_and_write_to_file(filename, hello) ? create_and_write_to_file(filename, hello) ?
assert u64(hello.len) == os.file_size(filename) assert hello.len == os.file_size(filename)
os.rm(filename) or { panic(err) } os.rm(filename) or { panic(err) }
} }
@ -138,7 +138,7 @@ fn test_write_and_read_string_to_file() {
filename := './test1.txt' filename := './test1.txt'
hello := 'hello world!' hello := 'hello world!'
os.write_file(filename, hello) or { panic(err) } os.write_file(filename, hello) or { panic(err) }
assert u64(hello.len) == os.file_size(filename) assert hello.len == os.file_size(filename)
read_hello := os.read_file(filename) or { panic('error reading file $filename') } read_hello := os.read_file(filename) or { panic('error reading file $filename') }
assert hello == read_hello assert hello == read_hello
os.rm(filename) or { panic(err) } os.rm(filename) or { panic(err) }
@ -157,7 +157,7 @@ fn test_write_and_read_bytes() {
// compare the length of the array with the file size (have to match). // compare the length of the array with the file size (have to match).
unsafe { file_write.write_ptr(payload.data, 5) } unsafe { file_write.write_ptr(payload.data, 5) }
file_write.close() file_write.close()
assert u64(payload.len) == os.file_size(file_name) assert payload.len == os.file_size(file_name)
mut file_read := os.open(os.real_path(file_name)) or { mut file_read := os.open(os.real_path(file_name)) or {
eprintln('failed to open file $file_name') eprintln('failed to open file $file_name')
return return
@ -355,12 +355,6 @@ fn test_mv() {
assert !os.is_dir(expected) assert !os.is_dir(expected)
} }
fn test_is_dir_empty() {
// Test that is_dir_empty returns true on
// non-existent directories ***as stated in it's doc string***
assert os.is_dir_empty('dir that does not exist at all')
}
fn test_cp_all() { fn test_cp_all() {
// fileX -> dir/fileX // fileX -> dir/fileX
// Note: clean up of the files happens inside the cleanup_leftovers function // Note: clean up of the files happens inside the cleanup_leftovers function
@ -792,7 +786,7 @@ fn test_truncate() ? {
mut f := os.create(filename) ? mut f := os.create(filename) ?
f.write_string(hello) ? f.write_string(hello) ?
f.close() f.close()
assert u64(hello.len) == os.file_size(filename) assert hello.len == os.file_size(filename)
newlen := u64(40000) newlen := u64(40000)
os.truncate(filename, newlen) or { panic(err) } os.truncate(filename, newlen) or { panic(err) }
assert newlen == os.file_size(filename) assert newlen == os.file_size(filename)

View File

@ -14,8 +14,7 @@ import strings
* Inits * Inits
* *
******************************************************************************/ ******************************************************************************/
// regex_base returns a regex object (`RE`) generated from `pattern` string and // regex create a regex object from the query string, retunr RE object and errors as re_err, err_pos
// detailed information in re_err, err_pos, if an error occurred.
pub fn regex_base(pattern string) (RE, int, int) { pub fn regex_base(pattern string) (RE, int, int) {
// init regex // init regex
mut re := RE{} mut re := RE{}

View File

@ -1,11 +1,13 @@
/*
* ATTENTION! Do not use this file as an example!
* For that, please look at `channel_select_2_test.v` or `channel_select_3_test.v`
*
* This test case uses the implementation in `sync/channels.v` directly
* in order to test it independently from the support in the core language
*/
module sync module sync
// vtest retry: 6
// ATTENTION! Do not use this file as an example!
// For that, please look at `channel_select_2_test.v` or `channel_select_3_test.v`
// This test case uses the implementation in `sync/channels.v` directly
// in order to test it independently from the support in the core language
import time import time
fn do_rec_i64(mut ch Channel) { fn do_rec_i64(mut ch Channel) {

View File

@ -18,7 +18,7 @@ fn test_count_10_times_1_cycle_should_result_10_cycles_with_sync() {
go count_one_cycle(mut counter, mut wg) go count_one_cycle(mut counter, mut wg)
} }
wg.wait() wg.wait()
assert counter.counter == u64(desired_iterations) assert counter.counter == desired_iterations
eprintln(' with synchronization the counter is: ${counter.counter:10} , expectedly == ${desired_iterations:10}') eprintln(' with synchronization the counter is: ${counter.counter:10} , expectedly == ${desired_iterations:10}')
} }

View File

@ -1821,9 +1821,6 @@ pub fn (stmt Stmt) check_c_expr() ? {
AssignStmt { AssignStmt {
return return
} }
ForCStmt, ForInStmt, ForStmt {
return
}
ExprStmt { ExprStmt {
if stmt.expr.is_expr() { if stmt.expr.is_expr() {
return return

View File

@ -206,14 +206,6 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
if v.pref.os == .macos && os.exists('/opt/procursus') { if v.pref.os == .macos && os.exists('/opt/procursus') {
ccoptions.linker_flags << '-Wl,-rpath,/opt/procursus/lib' ccoptions.linker_flags << '-Wl,-rpath,/opt/procursus/lib'
} }
mut user_darwin_version := 999_999_999
mut user_darwin_ppc := false
$if macos {
user_darwin_version = os.uname().release.split('.')[0].int()
if os.uname().machine == 'Power Macintosh' {
user_darwin_ppc = true
}
}
ccoptions.debug_mode = v.pref.is_debug ccoptions.debug_mode = v.pref.is_debug
ccoptions.guessed_compiler = v.pref.ccompiler ccoptions.guessed_compiler = v.pref.ccompiler
if ccoptions.guessed_compiler == 'cc' && v.pref.is_prod { if ccoptions.guessed_compiler == 'cc' && v.pref.is_prod {
@ -260,10 +252,7 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
} }
if ccoptions.is_cc_gcc { if ccoptions.is_cc_gcc {
if ccoptions.debug_mode { if ccoptions.debug_mode {
debug_options = ['-g'] debug_options = ['-g', '-no-pie']
if user_darwin_version > 9 {
debug_options << '-no-pie'
}
} }
optimization_options = ['-O3', '-fno-strict-aliasing', '-flto'] optimization_options = ['-O3', '-fno-strict-aliasing', '-flto']
} }
@ -345,7 +334,7 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
} }
// macOS code can include objective C TODO remove once objective C is replaced with C // macOS code can include objective C TODO remove once objective C is replaced with C
if v.pref.os == .macos || v.pref.os == .ios { if v.pref.os == .macos || v.pref.os == .ios {
if !ccoptions.is_cc_tcc && !user_darwin_ppc { if !ccoptions.is_cc_tcc {
ccoptions.source_args << '-x objective-c' ccoptions.source_args << '-x objective-c'
} }
} }

View File

@ -335,8 +335,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
left_elem_type := c.table.unaliased_type(left_info.elem_type) left_elem_type := c.table.unaliased_type(left_info.elem_type)
right_info := right_sym.info as ast.Array right_info := right_sym.info as ast.Array
right_elem_type := c.table.unaliased_type(right_info.elem_type) right_elem_type := c.table.unaliased_type(right_info.elem_type)
if left_type_unwrapped.nr_muls() == right_type_unwrapped.nr_muls() if left_info.nr_dims == right_info.nr_dims && left_elem_type == right_elem_type {
&& left_info.nr_dims == right_info.nr_dims && left_elem_type == right_elem_type {
continue continue
} }
} }

View File

@ -204,9 +204,7 @@ pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type,
} }
return return
} }
if got != ast.void_type { return error('cannot use `$got_typ_str` as `$expected_typ_str`')
return error('cannot use `$got_typ_str` as `$expected_typ_str`')
}
} }
// helper method to check if the type is of the same module. // helper method to check if the type is of the same module.
@ -691,38 +689,3 @@ pub fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr
c.need_recheck_generic_fns = true c.need_recheck_generic_fns = true
} }
} }
pub fn (c &Checker) sizeof_integer(a ast.Type) int {
t := if a in ast.unsigned_integer_type_idxs { a.flip_signedness() } else { a }
r := match t {
ast.char_type_idx, ast.i8_type_idx {
1
}
ast.i16_type_idx {
2
}
ast.int_type_idx {
4
}
ast.rune_type_idx {
4
}
ast.i64_type_idx {
8
}
ast.isize_type_idx {
if c.pref.m64 { 8 } else { 4 }
}
ast.int_literal_type {
s := c.table.type_to_str(a)
panic('`$s` has unknown size')
0
}
else {
s := c.table.type_to_str(a)
panic('`$s` is not an integer')
0
}
}
return r
}

View File

@ -640,18 +640,6 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
rt := c.table.sym(right_type).name rt := c.table.sym(right_type).name
c.error('negative value cannot be compared with `$rt`', node.left.pos) c.error('negative value cannot be compared with `$rt`', node.left.pos)
} }
} else if is_left_type_signed != is_right_type_signed
&& left_type != ast.int_literal_type_idx
&& right_type != ast.int_literal_type_idx {
ls := c.sizeof_integer(left_type)
rs := c.sizeof_integer(right_type)
// prevent e.g. `u32 == i16` but not `u16 == i32` as max_u16 fits in i32
// TODO u32 == i32, change < to <=
if (is_left_type_signed && ls < rs) || (is_right_type_signed && rs < ls) {
lt := c.table.sym(left_type).name
rt := c.table.sym(right_type).name
c.error('`$lt` cannot be compared with `$rt`', node.pos)
}
} }
} }
} }
@ -1675,9 +1663,7 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
c.inside_selector_expr = old_selector_expr c.inside_selector_expr = old_selector_expr
c.using_new_err_struct = using_new_err_struct_save c.using_new_err_struct = using_new_err_struct_save
if typ == ast.void_type_idx { if typ == ast.void_type_idx {
// This means that the field has an undefined type. c.error('`void` type has no fields', node.pos)
// This error was handled before.
// c.error('`void` type has no fields', node.pos)
return ast.void_type return ast.void_type
} }
node.expr_type = typ node.expr_type = typ
@ -3697,8 +3683,8 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
for mut expr is ast.ParExpr { for mut expr is ast.ParExpr {
expr = expr.expr expr = expr.expr
} }
if expr in [ast.BoolLiteral, ast.CallExpr, ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral, if expr in [ast.BoolLiteral, ast.CallExpr, ast.CharLiteral, ast.FloatLiteral,
ast.InfixExpr, ast.StringLiteral, ast.StringInterLiteral] { ast.IntegerLiteral, ast.InfixExpr, ast.StringLiteral, ast.StringInterLiteral] {
c.error('cannot take the address of $expr', node.pos) c.error('cannot take the address of $expr', node.pos)
} }
if mut node.right is ast.IndexExpr { if mut node.right is ast.IndexExpr {

View File

@ -578,17 +578,6 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
found = true found = true
return ast.string_type return ast.string_type
} }
if !found && node.left is ast.CallExpr {
c.expr(node.left)
expr := node.left as ast.CallExpr
sym := c.table.sym(expr.return_type)
if sym.kind == .function {
info := sym.info as ast.FnType
node.return_type = info.func.return_type
found = true
func = info.func
}
}
// already prefixed (mod.fn) or C/builtin/main // already prefixed (mod.fn) or C/builtin/main
if !found { if !found {
if f := c.table.find_fn(fn_name) { if f := c.table.find_fn(fn_name) {
@ -906,16 +895,6 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
if param.typ.has_flag(.generic) { if param.typ.has_flag(.generic) {
continue continue
} }
if param_typ_sym.kind == .array && arg_typ_sym.kind == .array {
param_info := param_typ_sym.info as ast.Array
param_elem_type := c.table.unaliased_type(param_info.elem_type)
arg_info := arg_typ_sym.info as ast.Array
arg_elem_type := c.table.unaliased_type(arg_info.elem_type)
if param.typ.nr_muls() == arg_typ.nr_muls()
&& param_info.nr_dims == arg_info.nr_dims && param_elem_type == arg_elem_type {
continue
}
}
if c.pref.translated || c.file.is_translated { if c.pref.translated || c.file.is_translated {
// TODO duplicated logic in check_types() (check_types.v) // TODO duplicated logic in check_types() (check_types.v)
// Allow enums to be used as ints and vice versa in translated code // Allow enums to be used as ints and vice versa in translated code
@ -1410,19 +1389,6 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
// if arg_typ_sym.kind == .string && typ_sym.has_method('str') { // if arg_typ_sym.kind == .string && typ_sym.has_method('str') {
// continue // continue
// } // }
param_typ_sym := c.table.sym(exp_arg_typ)
arg_typ_sym := c.table.sym(got_arg_typ)
if param_typ_sym.kind == .array && arg_typ_sym.kind == .array {
param_info := param_typ_sym.info as ast.Array
param_elem_type := c.table.unaliased_type(param_info.elem_type)
arg_info := arg_typ_sym.info as ast.Array
arg_elem_type := c.table.unaliased_type(arg_info.elem_type)
if exp_arg_typ.nr_muls() == got_arg_typ.nr_muls()
&& param_info.nr_dims == arg_info.nr_dims
&& param_elem_type == arg_elem_type {
continue
}
}
if got_arg_typ != ast.void_type { if got_arg_typ != ast.void_type {
c.error('$err.msg() in argument ${i + 1} to `${left_sym.name}.$method_name`', c.error('$err.msg() in argument ${i + 1} to `${left_sym.name}.$method_name`',
arg.pos) arg.pos)
@ -1777,9 +1743,6 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
mut ret_type := ast.void_type mut ret_type := ast.void_type
match method_name { match method_name {
'clone', 'move' { 'clone', 'move' {
if node.args.len != 0 {
c.error('`.${method_name}()` does not have any arguments', node.args[0].pos)
}
if method_name[0] == `m` { if method_name[0] == `m` {
c.fail_if_immutable(node.left) c.fail_if_immutable(node.left)
} }
@ -1791,9 +1754,6 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
ret_type = ret_type.clear_flag(.shared_f) ret_type = ret_type.clear_flag(.shared_f)
} }
'keys' { 'keys' {
if node.args.len != 0 {
c.error('`.keys()` does not have any arguments', node.args[0].pos)
}
info := left_sym.info as ast.Map info := left_sym.info as ast.Map
typ := c.table.find_or_register_array(info.key_type) typ := c.table.find_or_register_array(info.key_type)
ret_type = ast.Type(typ) ret_type = ast.Type(typ)
@ -1918,9 +1878,6 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
c.check_map_and_filter(false, elem_typ, node) c.check_map_and_filter(false, elem_typ, node)
node.return_type = ast.bool_type node.return_type = ast.bool_type
} else if method_name == 'clone' { } else if method_name == 'clone' {
if node.args.len != 0 {
c.error('`.clone()` does not have any arguments', node.args[0].pos)
}
// need to return `array_xxx` instead of `array` // need to return `array_xxx` instead of `array`
// in ['clone', 'str'] { // in ['clone', 'str'] {
node.receiver_type = left_type.ref() node.receiver_type = left_type.ref()
@ -1938,27 +1895,19 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
// c.warn('use `value in arr` instead of `arr.contains(value)`', node.pos) // c.warn('use `value in arr` instead of `arr.contains(value)`', node.pos)
if node.args.len != 1 { if node.args.len != 1 {
c.error('`.contains()` expected 1 argument, but got $node.args.len', node.pos) c.error('`.contains()` expected 1 argument, but got $node.args.len', node.pos)
} else if !left_sym.has_method('contains') { } else {
arg_typ := c.expr(node.args[0].expr) arg_typ := ast.mktyp(c.expr(node.args[0].expr))
c.check_expected_call_arg(arg_typ, elem_typ, node.language, node.args[0]) or { elem_typ_str := c.table.type_to_str(elem_typ)
c.error('$err.msg() in argument 1 to `.contains()`', node.args[0].pos) arg_typ_str := c.table.type_to_str(arg_typ)
if !left_sym.has_method('contains') && elem_typ_str != arg_typ_str {
c.error('`.contains()` expected `$elem_typ_str` argument, but got `$arg_typ_str`',
node.pos)
} }
} }
node.return_type = ast.bool_type node.return_type = ast.bool_type
} else if method_name == 'index' { } else if method_name == 'index' {
if node.args.len != 1 {
c.error('`.index()` expected 1 argument, but got $node.args.len', node.pos)
} else if !left_sym.has_method('index') {
arg_typ := c.expr(node.args[0].expr)
c.check_expected_call_arg(arg_typ, elem_typ, node.language, node.args[0]) or {
c.error('$err.msg() in argument 1 to `.index()`', node.args[0].pos)
}
}
node.return_type = ast.int_type node.return_type = ast.int_type
} else if method_name in ['first', 'last', 'pop'] { } else if method_name in ['first', 'last', 'pop'] {
if node.args.len != 0 {
c.error('`.${method_name}()` does not have any arguments', node.args[0].pos)
}
node.return_type = array_info.elem_type node.return_type = array_info.elem_type
if method_name == 'pop' { if method_name == 'pop' {
c.fail_if_immutable(node.left) c.fail_if_immutable(node.left)

View File

@ -95,9 +95,6 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
node.scope.update_var_type(node.key_var, key_type) node.scope.update_var_type(node.key_var, key_type)
} }
mut value_type := c.table.value_type(typ) mut value_type := c.table.value_type(typ)
if sym.kind == .string {
value_type = ast.byte_type
}
if value_type == ast.void_type || typ.has_flag(.optional) { if value_type == ast.void_type || typ.has_flag(.optional) {
if typ != ast.void_type { if typ != ast.void_type {
c.error('for in: cannot index `${c.table.type_to_str(typ)}`', node.cond.pos()) c.error('for in: cannot index `${c.table.type_to_str(typ)}`', node.cond.pos())

View File

@ -296,7 +296,7 @@ fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
c.smartcast_if_conds(node.right, mut scope) c.smartcast_if_conds(node.right, mut scope)
} else if node.op == .key_is { } else if node.op == .key_is {
right_expr := node.right right_expr := node.right
right_type := match right_expr { mut right_type := match right_expr {
ast.TypeNode { ast.TypeNode {
right_expr.typ right_expr.typ
} }
@ -308,10 +308,11 @@ fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
ast.Type(0) ast.Type(0)
} }
} }
right_type = c.unwrap_generic(right_type)
if right_type != ast.Type(0) { if right_type != ast.Type(0) {
left_sym := c.table.sym(node.left_type) left_sym := c.table.sym(node.left_type)
right_sym := c.table.sym(right_type) right_sym := c.table.sym(right_type)
mut expr_type := c.expr(node.left) mut expr_type := c.unwrap_generic(c.expr(node.left))
if left_sym.kind == .aggregate { if left_sym.kind == .aggregate {
expr_type = (left_sym.info as ast.Aggregate).sum_type expr_type = (left_sym.info as ast.Aggregate).sum_type
} }
@ -321,7 +322,7 @@ fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
} else { } else {
return return
} }
} else if !c.check_types(right_type, expr_type) && left_sym.kind != .sum_type { } else if !c.check_types(right_type, expr_type) {
expect_str := c.table.type_to_str(right_type) expect_str := c.table.type_to_str(right_type)
expr_str := c.table.type_to_str(expr_type) expr_str := c.table.type_to_str(expr_type)
c.error('cannot use type `$expect_str` as type `$expr_str`', node.pos) c.error('cannot use type `$expect_str` as type `$expr_str`', node.pos)

View File

@ -162,10 +162,9 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
c.expected_type = node.expected_type c.expected_type = node.expected_type
low_expr := expr.low low_expr := expr.low
high_expr := expr.high high_expr := expr.high
final_cond_sym := c.table.final_sym(node.cond_type)
if low_expr is ast.IntegerLiteral { if low_expr is ast.IntegerLiteral {
if high_expr is ast.IntegerLiteral if high_expr is ast.IntegerLiteral
&& (final_cond_sym.is_int() || final_cond_sym.info is ast.Enum) { && (cond_type_sym.is_int() || cond_type_sym.info is ast.Enum) {
low = low_expr.val.i64() low = low_expr.val.i64()
high = high_expr.val.i64() high = high_expr.val.i64()
if low > high { if low > high {
@ -175,7 +174,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
c.error('mismatched range types', low_expr.pos) c.error('mismatched range types', low_expr.pos)
} }
} else if low_expr is ast.CharLiteral { } else if low_expr is ast.CharLiteral {
if high_expr is ast.CharLiteral && final_cond_sym.kind in [.u8, .char, .rune] { if high_expr is ast.CharLiteral && cond_type_sym.kind in [.u8, .char, .rune] {
low = low_expr.val[0] low = low_expr.val[0]
high = high_expr.val[0] high = high_expr.val[0]
if low > high { if low > high {

View File

@ -34,7 +34,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
mut got_types := []ast.Type{} mut got_types := []ast.Type{}
mut expr_idxs := []int{} mut expr_idxs := []int{}
for i, expr in node.exprs { for i, expr in node.exprs {
mut typ := c.expr(expr) typ := c.expr(expr)
if typ == ast.void_type { if typ == ast.void_type {
c.error('`$expr` used as value', node.pos) c.error('`$expr` used as value', node.pos)
} }
@ -46,13 +46,6 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
expr_idxs << i expr_idxs << i
} }
} else { } else {
if expr is ast.Ident {
if expr.obj is ast.Var {
if expr.obj.smartcasts.len > 0 {
typ = c.unwrap_generic(expr.obj.smartcasts.last())
}
}
}
got_types << typ got_types << typ
expr_idxs << i expr_idxs << i
} }

View File

@ -1,28 +0,0 @@
vlib/v/checker/tests/array_builtin_method_args_err.vv:4:18: error: `.clone()` does not have any arguments
2 | arr := [1, 2, 3]
3 |
4 | a1 := arr.clone(22)
| ~~
5 | println(a1)
6 |
vlib/v/checker/tests/array_builtin_method_args_err.vv:7:18: error: `.first()` does not have any arguments
5 | println(a1)
6 |
7 | a2 := arr.first('a2')
| ~~~~
8 | println(a2)
9 |
vlib/v/checker/tests/array_builtin_method_args_err.vv:10:17: error: `.last()` does not have any arguments
8 | println(a2)
9 |
10 | a3 := arr.last(1)
| ^
11 | println(a3)
12 |
vlib/v/checker/tests/array_builtin_method_args_err.vv:13:16: error: `.pop()` does not have any arguments
11 | println(a3)
12 |
13 | a4 := arr.pop(2)
| ^
14 | println(a4)
15 | }

View File

@ -1,15 +0,0 @@
fn main() {
arr := [1, 2, 3]
a1 := arr.clone(22)
println(a1)
a2 := arr.first('a2')
println(a2)
a3 := arr.last(1)
println(a3)
a4 := arr.pop(2)
println(a4)
}

View File

@ -1,8 +1,8 @@
vlib/v/checker/tests/array_contains_args_err.vv:3:26: error: cannot use `[]int` as `int` in argument 1 to `.contains()` vlib/v/checker/tests/array_contains_args_err.vv:3:17: error: `.contains()` expected `int` argument, but got `[]int`
1 | fn main() { 1 | fn main() {
2 | arr := [0] 2 | arr := [0]
3 | mut ret := [0].contains([0]) 3 | mut ret := [0].contains([0])
| ~~~ | ~~~~~~~~~~~~~
4 | ret = [0].contains() 4 | ret = [0].contains()
5 | ret = [0, 1, 2].contains(0, 1, 2) 5 | ret = [0, 1, 2].contains(0, 1, 2)
vlib/v/checker/tests/array_contains_args_err.vv:4:12: error: `.contains()` expected 1 argument, but got 0 vlib/v/checker/tests/array_contains_args_err.vv:4:12: error: `.contains()` expected 1 argument, but got 0
@ -19,17 +19,17 @@ vlib/v/checker/tests/array_contains_args_err.vv:5:18: error: `.contains()` expec
| ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~
6 | ret = [0].contains('a') 6 | ret = [0].contains('a')
7 | ret = [0].contains(arr) 7 | ret = [0].contains(arr)
vlib/v/checker/tests/array_contains_args_err.vv:6:21: error: cannot use `string` as `int` in argument 1 to `.contains()` vlib/v/checker/tests/array_contains_args_err.vv:6:12: error: `.contains()` expected `int` argument, but got `string`
4 | ret = [0].contains() 4 | ret = [0].contains()
5 | ret = [0, 1, 2].contains(0, 1, 2) 5 | ret = [0, 1, 2].contains(0, 1, 2)
6 | ret = [0].contains('a') 6 | ret = [0].contains('a')
| ~~~ | ~~~~~~~~~~~~~
7 | ret = [0].contains(arr) 7 | ret = [0].contains(arr)
8 | println(ret) 8 | println(ret)
vlib/v/checker/tests/array_contains_args_err.vv:7:21: error: cannot use `[]int` as `int` in argument 1 to `.contains()` vlib/v/checker/tests/array_contains_args_err.vv:7:12: error: `.contains()` expected `int` argument, but got `[]int`
5 | ret = [0, 1, 2].contains(0, 1, 2) 5 | ret = [0, 1, 2].contains(0, 1, 2)
6 | ret = [0].contains('a') 6 | ret = [0].contains('a')
7 | ret = [0].contains(arr) 7 | ret = [0].contains(arr)
| ~~~ | ~~~~~~~~~~~~~
8 | println(ret) 8 | println(ret)
9 | } 9 | }

View File

@ -1,35 +0,0 @@
vlib/v/checker/tests/array_index_args_err.vv:3:23: error: cannot use `[]int` as `int` in argument 1 to `.index()`
1 | fn main() {
2 | arr := [0]
3 | mut ret := [0].index([0])
| ~~~
4 | ret = [0].index()
5 | ret = [0, 1, 2].index(0, 1, 2)
vlib/v/checker/tests/array_index_args_err.vv:4:12: error: `.index()` expected 1 argument, but got 0
2 | arr := [0]
3 | mut ret := [0].index([0])
4 | ret = [0].index()
| ~~~~~~~
5 | ret = [0, 1, 2].index(0, 1, 2)
6 | ret = [0].index('a')
vlib/v/checker/tests/array_index_args_err.vv:5:18: error: `.index()` expected 1 argument, but got 3
3 | mut ret := [0].index([0])
4 | ret = [0].index()
5 | ret = [0, 1, 2].index(0, 1, 2)
| ~~~~~~~~~~~~~~
6 | ret = [0].index('a')
7 | ret = [0].index(arr)
vlib/v/checker/tests/array_index_args_err.vv:6:18: error: cannot use `string` as `int` in argument 1 to `.index()`
4 | ret = [0].index()
5 | ret = [0, 1, 2].index(0, 1, 2)
6 | ret = [0].index('a')
| ~~~
7 | ret = [0].index(arr)
8 | println(ret)
vlib/v/checker/tests/array_index_args_err.vv:7:18: error: cannot use `[]int` as `int` in argument 1 to `.index()`
5 | ret = [0, 1, 2].index(0, 1, 2)
6 | ret = [0].index('a')
7 | ret = [0].index(arr)
| ~~~
8 | println(ret)
9 | }

View File

@ -1,9 +0,0 @@
fn main() {
arr := [0]
mut ret := [0].index([0])
ret = [0].index()
ret = [0, 1, 2].index(0, 1, 2)
ret = [0].index('a')
ret = [0].index(arr)
println(ret)
}

View File

@ -17,45 +17,10 @@ vlib/v/checker/tests/compare_unsigned_signed.vv:10:16: error: `u8` cannot be com
10 | _ = u8(-1) == -1 // false! 10 | _ = u8(-1) == -1 // false!
| ~~ | ~~
11 | _ = -1 == u16(-1) // false! 11 | _ = -1 == u16(-1) // false!
12 | 12 | }
vlib/v/checker/tests/compare_unsigned_signed.vv:11:6: error: negative value cannot be compared with `u16` vlib/v/checker/tests/compare_unsigned_signed.vv:11:6: error: negative value cannot be compared with `u16`
9 | // unsigned == literal 9 | // unsigned == literal
10 | _ = u8(-1) == -1 // false! 10 | _ = u8(-1) == -1 // false!
11 | _ = -1 == u16(-1) // false! 11 | _ = -1 == u16(-1) // false!
| ~~ | ~~
12 | 12 | }
13 | // smaller unsigned == signed, OK
vlib/v/checker/tests/compare_unsigned_signed.vv:18:12: error: `i8` cannot be compared with `u16`
16 |
17 | // smaller signed == unsigned, NG
18 | _ = i8(0) == u16(0)
| ~~
19 | _ = i16(0) != u32(0)
20 | _ = int(0) == u64(0)
vlib/v/checker/tests/compare_unsigned_signed.vv:19:13: error: `i16` cannot be compared with `u32`
17 | // smaller signed == unsigned, NG
18 | _ = i8(0) == u16(0)
19 | _ = i16(0) != u32(0)
| ~~
20 | _ = int(0) == u64(0)
21 | _ = i32(0) == u64(0) // FIXME
vlib/v/checker/tests/compare_unsigned_signed.vv:20:13: error: `int` cannot be compared with `u64`
18 | _ = i8(0) == u16(0)
19 | _ = i16(0) != u32(0)
20 | _ = int(0) == u64(0)
| ~~
21 | _ = i32(0) == u64(0) // FIXME
22 | // swap order
vlib/v/checker/tests/compare_unsigned_signed.vv:23:13: error: `u16` cannot be compared with `i8`
21 | _ = i32(0) == u64(0) // FIXME
22 | // swap order
23 | _ = u16(0) == i8(0)
| ~~
24 | _ = u64(0) == i16(0)
25 | }
vlib/v/checker/tests/compare_unsigned_signed.vv:24:13: error: `u64` cannot be compared with `i16`
22 | // swap order
23 | _ = u16(0) == i8(0)
24 | _ = u64(0) == i16(0)
| ~~
25 | }

View File

@ -9,17 +9,4 @@ fn main() {
// unsigned == literal // unsigned == literal
_ = u8(-1) == -1 // false! _ = u8(-1) == -1 // false!
_ = -1 == u16(-1) // false! _ = -1 == u16(-1) // false!
// smaller unsigned == signed, OK
_ = u16(-1) == int(-1)
_ = int(-1) != u8(-1)
// smaller signed == unsigned, NG
_ = i8(0) == u16(0)
_ = i16(0) != u32(0)
_ = int(0) == u64(0)
_ = i32(0) == u64(0) // FIXME
// swap order
_ = u16(0) == i8(0)
_ = u64(0) == i16(0)
} }

View File

@ -1,3 +1,10 @@
vlib/v/checker/tests/if_match_expr.vv:8:6: error: `if` expression branch has unsupported statement (`v.ast.ForStmt`)
6 | if true {1} else {-1} // result
7 | } else {
8 | for {break}
| ^
9 | {}
10 | match true {true {} else {}} // statement not expression
vlib/v/checker/tests/if_match_expr.vv:9:2: error: `if` expression branch has unsupported statement (`v.ast.Block`) vlib/v/checker/tests/if_match_expr.vv:9:2: error: `if` expression branch has unsupported statement (`v.ast.Block`)
7 | } else { 7 | } else {
8 | for {break} 8 | for {break}

View File

@ -1,21 +0,0 @@
vlib/v/checker/tests/map_builtin_method_args_err.vv:4:16: error: `.clone()` does not have any arguments
2 | mut m := {11: 22}
3 |
4 | a1 := m.clone(11)
| ~~
5 | println(a1)
6 |
vlib/v/checker/tests/map_builtin_method_args_err.vv:7:15: error: `.move()` does not have any arguments
5 | println(a1)
6 |
7 | a2 := m.move(11)
| ~~
8 | println(a2)
9 |
vlib/v/checker/tests/map_builtin_method_args_err.vv:10:15: error: `.keys()` does not have any arguments
8 | println(a2)
9 |
10 | a3 := m.keys('aaa')
| ~~~~~
11 | println(a3)
12 | }

View File

@ -1,12 +0,0 @@
fn main() {
mut m := {11: 22}
a1 := m.clone(11)
println(a1)
a2 := m.move(11)
println(a2)
a3 := m.keys('aaa')
println(a3)
}

View File

@ -511,13 +511,8 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
return res return res
} }
ast.AnonFn, ast.ArrayDecompose, ast.AsCast, ast.Assoc, ast.AtExpr, ast.CTempVar, else {
ast.ChanInit, ast.Comment, ast.ComptimeCall, ast.ComptimeSelector, ast.ComptimeType, e.error('unhandled expression $expr.type_name()')
ast.ConcatExpr, ast.DumpExpr, ast.EmptyExpr, ast.EnumVal, ast.GoExpr, ast.IfGuardExpr,
ast.IndexExpr, ast.IsRefType, ast.Likely, ast.LockExpr, ast.MapInit, ast.MatchExpr,
ast.NodeError, ast.None, ast.OffsetOf, ast.OrExpr, ast.RangeExpr, ast.SelectExpr,
ast.SqlExpr, ast.TypeNode, ast.TypeOf, ast.UnsafeExpr {
e.error('unhandled expression ${typeof(expr).name}')
} }
} }
return empty return empty

View File

@ -1462,7 +1462,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
|| f.line_len + expr.pos().len > fmt.max_len[3] || f.line_len + expr.pos().len > fmt.max_len[3]
} }
} }
mut line_break := f.array_init_break[f.array_init_depth - 1] line_break := f.array_init_break[f.array_init_depth - 1]
mut penalty := if line_break { 0 } else { 4 } mut penalty := if line_break { 0 } else { 4 }
if penalty > 0 { if penalty > 0 {
if i == 0 if i == 0
@ -1480,26 +1480,14 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
} }
single_line_expr := expr_is_single_line(expr) single_line_expr := expr_is_single_line(expr)
if single_line_expr { if single_line_expr {
mut estr := '' estr := f.node_str(expr)
if !is_new_line && !f.buffering && f.line_len + expr.pos().len > fmt.max_len.last() { if !is_new_line && !f.buffering && f.line_len + estr.len > fmt.max_len.last() {
if inc_indent {
estr = f.node_str(expr)
}
f.writeln('') f.writeln('')
is_new_line = true is_new_line = true
if !inc_indent { if !inc_indent {
f.indent++ f.indent++
inc_indent = true inc_indent = true
f.write_indent()
f.empty_line = false
estr = f.node_str(expr)
} }
if i == 0 {
f.array_init_break[f.array_init_depth - 1] = true
line_break = true
}
} else {
estr = f.node_str(expr)
} }
if !is_new_line && i > 0 { if !is_new_line && i > 0 {
f.write(' ') f.write(' ')
@ -2327,11 +2315,7 @@ pub fn (mut f Fmt) par_expr(node ast.ParExpr) {
f.par_level++ f.par_level++
f.write('(') f.write('(')
} }
mut expr := node.expr f.expr(node.expr)
for mut expr is ast.ParExpr {
expr = expr.expr
}
f.expr(expr)
if requires_paren { if requires_paren {
f.par_level-- f.par_level--
f.write(')') f.write(')')

View File

@ -6,7 +6,8 @@ const (
header: { header: {
'Set-Cookie': ['special-7=","'] 'Set-Cookie': ['special-7=","']
} }
cookies: [&http.Cookie{ cookies: [
&http.Cookie{
name: 'special-7' name: 'special-7'
value: ',' value: ','
raw: 'special-8=","' raw: 'special-8=","'

View File

@ -12,13 +12,6 @@ fn wrapping_tests() {
'elit. Donec varius purus leo, vel maximus diam', 'elit. Donec varius purus leo, vel maximus diam',
'finibus sed. Etiam eu urna ante. Nunc quis vehicula', 'finibus sed. Etiam eu urna ante. Nunc quis vehicula',
'velit. Sed at mauris et quam ornare tristique.'] 'velit. Sed at mauris et quam ornare tristique.']
multi_level := [
[1, 2, 3],
[
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec varius purus leo, vel maximus diam',
'finibus sed. Etiam eu urna ante. Nunc quis vehicula velit. Sed at mauris et quam ornare tristique.',
],
]
} }
fn array_init_without_commas() { fn array_init_without_commas() {

View File

@ -9,10 +9,6 @@ fn main() {
fn wrapping_tests() { fn wrapping_tests() {
my_arr := ['Lorem ipsum dolor sit amet, consectetur adipiscing', 'elit. Donec varius purus leo, vel maximus diam', 'finibus sed. Etiam eu urna ante. Nunc quis vehicula', 'velit. Sed at mauris et quam ornare tristique.'] my_arr := ['Lorem ipsum dolor sit amet, consectetur adipiscing', 'elit. Donec varius purus leo, vel maximus diam', 'finibus sed. Etiam eu urna ante. Nunc quis vehicula', 'velit. Sed at mauris et quam ornare tristique.']
multi_level := [
[1, 2, 3],
['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec varius purus leo, vel maximus diam', 'finibus sed. Etiam eu urna ante. Nunc quis vehicula velit. Sed at mauris et quam ornare tristique.'],
]
} }
fn array_init_without_commas() { fn array_init_without_commas() {

View File

@ -1,6 +0,0 @@
fn main() {
_, _ := (22 > 11), (43 > 22)
_ := (10 + 11)
_ := (11 * 2)
_ := (11 * 2)
}

View File

@ -1,6 +0,0 @@
fn main() {
_, _ := (((22 > 11))), (43 > 22)
_ := ((10 + 11))
_ := ((((((11 * 2))))))
_ := ((11 * 2))
}

View File

@ -78,7 +78,7 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
g.inside_lambda = false g.inside_lambda = false
return return
} }
need_tmp_var := g.inside_call && !g.inside_struct_init && node.exprs.len == 0 need_tmp_var := g.inside_call && !g.inside_struct_init
mut stmt_str := '' mut stmt_str := ''
mut tmp_var := '' mut tmp_var := ''
if need_tmp_var { if need_tmp_var {

View File

@ -314,32 +314,11 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
} }
func := right_sym.info as ast.FnType func := right_sym.info as ast.FnType
ret_styp := g.typ(func.func.return_type) ret_styp := g.typ(func.func.return_type)
g.write('$ret_styp (*${g.get_ternary_name(ident.name)}) (')
mut call_conv := ''
mut msvc_call_conv := ''
for attr in func.func.attrs {
match attr.name {
'callconv' {
if g.is_cc_msvc {
msvc_call_conv = '__$attr.arg '
} else {
call_conv = '$attr.arg'
}
}
else {}
}
}
call_conv_attribute_suffix := if call_conv.len != 0 {
'__attribute__(($call_conv))'
} else {
''
}
g.write('$ret_styp ($msvc_call_conv*${g.get_ternary_name(ident.name)}) (')
def_pos := g.definitions.len def_pos := g.definitions.len
g.fn_decl_params(func.func.params, voidptr(0), false) g.fn_decl_params(func.func.params, voidptr(0), false)
g.definitions.go_back(g.definitions.len - def_pos) g.definitions.go_back(g.definitions.len - def_pos)
g.write(')$call_conv_attribute_suffix') g.write(')')
} else { } else {
if is_decl { if is_decl {
if is_inside_ternary { if is_inside_ternary {

View File

@ -3286,7 +3286,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
if field_sym.kind == .sum_type { if field_sym.kind == .sum_type {
g.write('*') g.write('*')
} }
cast_sym := g.table.sym(g.unwrap_generic(typ)) cast_sym := g.table.sym(typ)
if i != 0 { if i != 0 {
dot := if field.typ.is_ptr() { '->' } else { '.' } dot := if field.typ.is_ptr() { '->' } else { '.' }
sum_type_deref_field += ')$dot' sum_type_deref_field += ')$dot'
@ -5185,13 +5185,11 @@ fn (mut g Gen) enum_val(node ast.EnumVal) {
// g.write('${it.mod}${it.enum_name}_$it.val') // g.write('${it.mod}${it.enum_name}_$it.val')
// g.enum_expr(node) // g.enum_expr(node)
styp := g.typ(g.table.unaliased_type(node.typ)) styp := g.typ(g.table.unaliased_type(node.typ))
// && g.inside_switch if node.typ.is_number() {
if g.pref.translated && node.typ.is_number() {
// Mostly in translated code, when C enums are used as ints in switches // Mostly in translated code, when C enums are used as ints in switches
g.write('/*enum val is_number $node.mod styp=$styp*/_const_main__$node.val') // g.write('/*enum val is_number $node.mod styp=$styp*/')
} else {
g.write('${styp}__$node.val')
} }
g.write('${styp}__$node.val')
} }
fn (mut g Gen) as_cast(node ast.AsCast) { fn (mut g Gen) as_cast(node ast.AsCast) {

View File

@ -379,10 +379,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
defer { defer {
g.tmp_count = ctmp g.tmp_count = ctmp
} }
prev_inside_ternary := g.inside_ternary
g.inside_ternary = 0
g.stmts(node.stmts) g.stmts(node.stmts)
g.inside_ternary = prev_inside_ternary
if node.is_noreturn { if node.is_noreturn {
g.writeln('\twhile(1);') g.writeln('\twhile(1);')
} }
@ -640,12 +637,11 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
// see my comment in parser near anon_fn // see my comment in parser near anon_fn
if node.left is ast.AnonFn { if node.left is ast.AnonFn {
g.expr(node.left) g.expr(node.left)
} else if node.left is ast.IndexExpr && node.name == '' { }
if node.left is ast.IndexExpr && node.name == '' {
g.is_fn_index_call = true g.is_fn_index_call = true
g.expr(node.left) g.expr(node.left)
g.is_fn_index_call = false g.is_fn_index_call = false
} else if node.left is ast.CallExpr && node.name == '' {
g.expr(node.left)
} }
if node.should_be_skipped { if node.should_be_skipped {
return return
@ -945,7 +941,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.gen_expr_to_string(node.left, rec_type) g.gen_expr_to_string(node.left, rec_type)
return return
} else if node.left.obj.smartcasts.len > 0 { } else if node.left.obj.smartcasts.len > 0 {
rec_type = g.unwrap_generic(node.left.obj.smartcasts.last()) rec_type = node.left.obj.smartcasts.last()
cast_sym := g.table.sym(rec_type) cast_sym := g.table.sym(rec_type)
if cast_sym.info is ast.Aggregate { if cast_sym.info is ast.Aggregate {
rec_type = cast_sym.info.types[g.aggregate_type_idx] rec_type = cast_sym.info.types[g.aggregate_type_idx]
@ -1335,7 +1331,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
if expr.obj is ast.Var { if expr.obj is ast.Var {
typ = expr.obj.typ typ = expr.obj.typ
if expr.obj.smartcasts.len > 0 { if expr.obj.smartcasts.len > 0 {
typ = g.unwrap_generic(expr.obj.smartcasts.last()) typ = expr.obj.smartcasts.last()
cast_sym := g.table.sym(typ) cast_sym := g.table.sym(typ)
if cast_sym.info is ast.Aggregate { if cast_sym.info is ast.Aggregate {
typ = cast_sym.info.types[g.aggregate_type_idx] typ = cast_sym.info.types[g.aggregate_type_idx]
@ -2044,12 +2040,6 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as
g.expr(arg.expr) g.expr(arg.expr)
g.write('->val') g.write('->val')
return return
} else if arg.expr is ast.ArrayInit {
if arg.expr.is_fixed {
if !arg.expr.has_it {
g.write('(${g.typ(arg.expr.typ)})')
}
}
} }
g.expr_with_cast(arg.expr, arg_typ, expected_type) g.expr_with_cast(arg.expr, arg_typ, expected_type)
if needs_closing { if needs_closing {

View File

@ -299,15 +299,14 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
} else { } else {
node.cond node.cond
} }
field_accessor := if node.cond_type.is_ptr() { '->' } else { '.' }
i := if node.key_var in ['', '_'] { g.new_tmp_var() } else { node.key_var } i := if node.key_var in ['', '_'] { g.new_tmp_var() } else { node.key_var }
g.write('for (int $i = 0; $i < ') g.write('for (int $i = 0; $i < ')
g.expr(cond) g.expr(cond)
g.writeln('${field_accessor}len; ++$i) {') g.writeln('.len; ++$i) {')
if node.val_var != '_' { if node.val_var != '_' {
g.write('\tu8 ${c_name(node.val_var)} = ') g.write('\tbyte ${c_name(node.val_var)} = ')
g.expr(cond) g.expr(cond)
g.writeln('${field_accessor}str[$i];') g.writeln('.str[$i];')
} }
} else if node.kind == .struct_ { } else if node.kind == .struct_ {
cond_type_sym := g.table.sym(node.cond_type) cond_type_sym := g.table.sym(node.cond_type)

View File

@ -20,9 +20,6 @@ fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool {
if is_noreturn_callexpr(stmt.expr) { if is_noreturn_callexpr(stmt.expr) {
return true return true
} }
if stmt.expr is ast.MatchExpr {
return true
}
if stmt.expr is ast.CallExpr { if stmt.expr is ast.CallExpr {
if stmt.expr.is_method { if stmt.expr.is_method {
left_sym := g.table.sym(stmt.expr.receiver_type) left_sym := g.table.sym(stmt.expr.receiver_type)

View File

@ -708,8 +708,7 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
g.write(', _MOV(($elem_type_str[]){ ') g.write(', _MOV(($elem_type_str[]){ ')
} }
// if g.autofree // if g.autofree
needs_clone := !g.is_builtin_mod && array_info.elem_type.idx() == ast.string_type_idx needs_clone := array_info.elem_type.idx() == ast.string_type_idx && !g.is_builtin_mod
&& array_info.elem_type.nr_muls() == 0
if needs_clone { if needs_clone {
g.write('string_clone(') g.write('string_clone(')
} }

View File

@ -61,7 +61,8 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
} }
g.inside_match_optional = true g.inside_match_optional = true
} }
if node.cond in [ast.Ident, ast.SelectorExpr, ast.IntegerLiteral, ast.StringLiteral, ast.FloatLiteral] { if node.cond in [ast.Ident, ast.SelectorExpr, ast.IntegerLiteral, ast.StringLiteral,
ast.FloatLiteral] {
cond_var = g.expr_string(node.cond) cond_var = g.expr_string(node.cond)
} else { } else {
line := if is_expr { line := if is_expr {

View File

@ -156,7 +156,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) {
if g.comptime_var_type_map.len > 0 || g.comptime_for_method.len > 0 { if g.comptime_var_type_map.len > 0 || g.comptime_for_method.len > 0 {
exp_typ = expr.obj.typ exp_typ = expr.obj.typ
} else if expr.obj.smartcasts.len > 0 { } else if expr.obj.smartcasts.len > 0 {
exp_typ = g.unwrap_generic(expr.obj.smartcasts.last()) exp_typ = expr.obj.smartcasts.last()
cast_sym := g.table.sym(exp_typ) cast_sym := g.table.sym(exp_typ)
if cast_sym.info is ast.Aggregate { if cast_sym.info is ast.Aggregate {
exp_typ = cast_sym.info.types[g.aggregate_type_idx] exp_typ = cast_sym.info.types[g.aggregate_type_idx]

View File

@ -2426,8 +2426,8 @@ fn (mut g JsGen) match_expr(node ast.MatchExpr) {
g.inside_ternary = true g.inside_ternary = true
} }
if node.cond in [ast.Ident, ast.SelectorExpr, ast.IntegerLiteral, ast.StringLiteral, ast.FloatLiteral, if node.cond in [ast.Ident, ast.SelectorExpr, ast.IntegerLiteral, ast.StringLiteral,
ast.CallExpr, ast.EnumVal] { ast.FloatLiteral, ast.CallExpr, ast.EnumVal] {
cond_var = CondExpr{node.cond} cond_var = CondExpr{node.cond}
} else { } else {
s := g.new_tmp_var() s := g.new_tmp_var()

View File

@ -783,10 +783,9 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
} else { } else {
p.tok.lit p.tok.lit
} }
is_generic_type := p.tok.kind == .name && p.tok.lit.len == 1 && p.tok.lit[0].is_capital()
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn, .lsbr] types_only := p.tok.kind in [.amp, .ellipsis, .key_fn, .lsbr]
|| (p.peek_tok.kind == .comma && (p.table.known_type(argname) || is_generic_type)) || (p.peek_tok.kind == .comma && p.table.known_type(argname))
|| p.peek_tok.kind == .dot || p.peek_tok.kind == .rpar || p.peek_tok.kind == .dot || p.peek_tok.kind == .rpar
|| (p.tok.kind == .key_mut && (p.peek_token(2).kind == .comma || (p.tok.kind == .key_mut && (p.peek_token(2).kind == .comma
|| p.peek_token(2).kind == .rpar || (p.peek_tok.kind == .name || p.peek_token(2).kind == .rpar || (p.peek_tok.kind == .name

View File

@ -791,7 +791,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
spos := p.tok.pos() spos := p.tok.pos()
name := p.check_name() name := p.check_name()
if name in p.label_names { if name in p.label_names {
return p.error_with_pos('duplicate label `$name`', spos) p.error_with_pos('duplicate label `$name`', spos)
} }
p.label_names << name p.label_names << name
p.next() p.next()
@ -812,7 +812,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
return stmt return stmt
} }
else { else {
return p.error_with_pos('unknown kind of For statement', for_pos) p.error_with_pos('unknown kind of For statement', for_pos)
} }
} }
} }
@ -2327,18 +2327,6 @@ pub fn (mut p Parser) name_expr() ast.Expr {
p.error_with_pos('unexpected $p.prev_tok', p.prev_tok.pos()) p.error_with_pos('unexpected $p.prev_tok', p.prev_tok.pos())
} }
node = p.call_expr(language, mod) node = p.call_expr(language, mod)
if p.tok.kind == .lpar && p.prev_tok.line_nr == p.tok.line_nr {
p.next()
pos := p.tok.pos()
args := p.call_args()
p.check(.rpar)
node = ast.CallExpr{
left: node
args: args
pos: pos
scope: p.scope
}
}
} }
} else if (p.peek_tok.kind == .lcbr || (p.peek_tok.kind == .lt && lit0_is_capital)) } else if (p.peek_tok.kind == .lcbr || (p.peek_tok.kind == .lt && lit0_is_capital))
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital)) && (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))

View File

@ -256,27 +256,30 @@ fn vweb_tmpl_${fn_name}() string {
match state { match state {
.html { .html {
line_t := line.trim_space() if line.starts_with('span.') && line.ends_with('{') {
if line_t.starts_with('span.') && line.ends_with('{') {
// `span.header {` => `<span class='header'>` // `span.header {` => `<span class='header'>`
class := line.find_between('span.', '{').trim_space() class := line.find_between('span.', '{').trim_space()
source.writeln('<span class="$class">') source.writeln('<span class="$class">')
in_span = true in_span = true
continue continue
} else if line_t.starts_with('.') && line.ends_with('{') { }
if line.trim_space().starts_with('.') && line.ends_with('{') {
// `.header {` => `<div class='header'>` // `.header {` => `<div class='header'>`
class := line.find_between('.', '{').trim_space() class := line.find_between('.', '{').trim_space()
trimmed := line.trim_space() trimmed := line.trim_space()
source.write_string(strings.repeat(`\t`, line.len - trimmed.len)) // add the necessary indent to keep <div><div><div> code clean source.write_string(strings.repeat(`\t`, line.len - trimmed.len)) // add the necessary indent to keep <div><div><div> code clean
source.writeln('<div class="$class">') source.writeln('<div class="$class">')
continue continue
} else if line_t.starts_with('#') && line.ends_with('{') { }
if line.starts_with('#') && line.ends_with('{') {
// `#header {` => `<div id='header'>` // `#header {` => `<div id='header'>`
class := line.find_between('#', '{').trim_space() class := line.find_between('#', '{').trim_space()
source.writeln('<div id="$class">') source.writeln('<div id="$class">')
continue continue
} else if line_t == '}' { }
source.write_string(strings.repeat(`\t`, line.len - line_t.len)) // add the necessary indent to keep <div><div><div> code clean if line.trim_space() == '}' {
trimmed := line.trim_space()
source.write_string(strings.repeat(`\t`, line.len - trimmed.len)) // add the necessary indent to keep <div><div><div> code clean
if in_span { if in_span {
source.writeln('</span>') source.writeln('</span>')
in_span = false in_span = false

View File

@ -1,25 +0,0 @@
fn foofun(op rune) fn () string {
return match op {
`1` {
fn () string {
return '1 passed'
}
}
`2` {
fn () string {
return '2 passed'
}
}
else {
fn () string {
return 'Nor 1 or 2 passed'
}
}
}
}
fn test_anon_fn_decl_inside_ternary() {
a := foofun(`1`)
println(a())
assert a() == '1 passed'
}

View File

@ -1,19 +0,0 @@
fn foofun1(op string) fn () string {
return fn () string {
return 'x passed'
}
}
fn foofun2(op string) fn () int {
return fn () int {
return 22
}
}
fn test_fn_call_using_anon_fn_call_arg() {
println(main.foofun1('1')())
assert main.foofun1('1')() == 'x passed'
println(main.foofun2('1')())
assert main.foofun2('1')() == 22
}

View File

@ -1,24 +0,0 @@
fn show_array_of_u8(data []u8) string {
println(data)
return '$data'
}
struct Foo {}
fn (f Foo) show_array_of_u8(data []u8) string {
println(data)
return '$data'
}
fn test_fn_with_array_of_aliases_argument() {
a := [byte(1), 2, 3]
s1 := show_array_of_u8(a)
println(s1)
assert s1 == '[0x01, 0x02, 0x03]'
foo := Foo{}
s2 := foo.show_array_of_u8(a)
println(s2)
assert s2 == '[0x01, 0x02, 0x03]'
}

View File

@ -1,30 +0,0 @@
interface Any {}
struct ConcreteA {
a int
}
struct ConcreteB {
b int
}
struct Container {
concrete_a Any
concrete_b Any
}
fn cast_struct<T>(any_struct Any) &T {
if any_struct is T {
return any_struct
}
panic('cannot cast')
}
fn test_generic_empty_interface_to_multi_struct() {
concrete_a := cast_struct<ConcreteA>(ConcreteA{12345})
concrete_b := cast_struct<ConcreteB>(ConcreteB{54321})
println(concrete_a.a)
println(concrete_b.b)
assert concrete_a.a == 12345
assert concrete_b.b == 54321
}

View File

@ -1,13 +0,0 @@
fn test_generics_anon_fn_decl_with_type_only_arg() {
ret := func_b<int>(11, 22, add)
println(ret)
assert ret == 33
}
fn add(a int, b int) int {
return a + b
}
fn func_b<T>(x T, y T, f fn (T, T) T) T {
return f(x, y)
}

View File

@ -1,5 +1,3 @@
// vtest retry: 3
fn sum1(a int, b int) int { fn sum1(a int, b int) int {
sum_func1 := fn (a int, b int) int { sum_func1 := fn (a int, b int) int {
return a + b return a + b

View File

@ -1,12 +0,0 @@
fn test_if_expr_with_nested_match_expr() {
a := if true {
match `a` {
`a` { 0 }
else { 1 }
}
} else {
3
}
println(a)
assert a == 0
}

View File

@ -42,9 +42,9 @@ fn test_cmp_u32_and_signed() {
fn test_cmp_signed_and_u64() { fn test_cmp_signed_and_u64() {
// == // ==
// assert int(1) == u64(1) assert int(1) == u64(1)
// != // !=
// assert int(1) != u64(2) assert int(1) != u64(2)
// > // >
assert !(int(1) > u64(1)) assert !(int(1) > u64(1))
assert int(1) > u64(0) assert int(1) > u64(0)
@ -63,9 +63,9 @@ fn test_cmp_signed_and_u64() {
fn test_cmp_u64_and_signed() { fn test_cmp_u64_and_signed() {
// == // ==
// assert u64(1) == int(1) assert u64(1) == int(1)
// != // !=
// assert u64(2) != int(1) assert u64(2) != int(1)
// > // >
assert !(u64(1) > int(1)) assert !(u64(1) > int(1))
assert u64(1) > int(0) assert u64(1) > int(0)

View File

@ -1,11 +0,0 @@
97
98
99
abc
23
77
abc
> k: abc | v: xyz
> k: def | v: jkl
abc
abc

View File

@ -1,30 +0,0 @@
interface Any {}
fn abc(a Any) {
if a is string {
for x in a {
println(x)
}
}
if a is []u8 {
for x in a {
println(x)
}
}
if a is map[string]string {
for k, v in a {
println('> k: $k | v: $v')
}
}
println(@FN)
}
fn main() {
abc('abc')
abc([u8(23), 77])
abc({
'abc': 'xyz'
'def': 'jkl'
})
abc(123)
}

View File

@ -1 +0,0 @@
[[1, 2], [3, 3]]

View File

@ -1,4 +0,0 @@
fn main() {
a := [[1, 2]!, [3, 3]!]!
println([[a[0][0], a[0][1]]!, [a[1][0], a[1][1]]!]!)
}

View File

@ -1,9 +0,0 @@
fn test_match_aliases() {
a := byte(97)
ret := match a {
`0`...`9`, `a`...`f` { 'OK' }
else { 'NOT OK' }
}
println(ret)
assert ret == 'OK'
}

View File

@ -1,58 +0,0 @@
fn test_match_with_for_in_loop() {
a := 101
b := match a {
101 {
mut aa := []int{}
for i in 0 .. 3 {
aa << i
}
aa
}
else {
[0]
}
}
println(b)
assert b == [0, 1, 2]
}
fn test_match_with_for_c_loop() {
a := 101
b := match a {
101 {
mut aa := []int{}
for i := 0; i < 3; i++ {
aa << i
}
aa
}
else {
[0]
}
}
println(b)
assert b == [0, 1, 2]
}
fn test_match_with_for_loop() {
a := 101
b := match a {
101 {
mut aa := []int{}
mut i := 0
for {
aa << i
i++
if i == 3 {
break
}
}
aa
}
else {
[0]
}
}
println(b)
assert b == [0, 1, 2]
}

View File

@ -58,13 +58,13 @@ fn test_shift_operators() {
assert e == a assert e == a
mut e3 := u64(1) mut e3 := u64(1)
e3 <<= u32(i) e3 <<= u32(i)
assert e3 == u64(b) assert e3 == b
e3 >>= u32(i) e3 >>= u32(i)
assert e == a assert e == a
e3 <<= u64(i) e3 <<= u64(i)
assert e3 == u64(b) assert e3 == b
e3 >>= u64(i) e3 >>= u64(i)
assert e3 == u64(a) assert e3 == a
// Test shifts with custom int types // Test shifts with custom int types
x := MyInt(2) x := MyInt(2)
assert x << 2 == 8 assert x << 2 == 8

View File

@ -1,18 +1,7 @@
fn test_creating_an_array_of_string_reference() { fn test_str_array_of_reference() {
names := ['John', 'Paul', 'George', 'Ringo'] names := ['John', 'Paul', 'George', 'Ringo']
a := unsafe { [&names[0], &names[1]] } a := unsafe { [&names[0], &names[1]] }
println(a[0]) println(a[0])
println(a) println(a)
assert '$a' == "[&'John', &'Paul']" assert '$a' == "[&'John', &'Paul']"
assert typeof(a[0]).name == '&string'
}
fn test_pushing_to_an_array_of_string_references() {
mut a := []&string{}
v1 := 'abc'
v2 := 'def'
a << &v1
a << &v2
assert *(a[0]) == 'abc'
assert *(a[1]) == 'def'
} }