diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 4f1587e272..646899e055 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -73,7 +73,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string for file in files { g.file = file // println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len') - building_v := g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v') + building_v := true && (g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v')) is_test := g.file.path.ends_with('.vv') || g.file.path.ends_with('_test.v') if g.file.path.ends_with('_test.v') { g.is_test = is_test @@ -454,7 +454,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.write('; $i < ') g.expr(it.high) g.writeln('; $i++) { ') - g.writeln('int $it.val_var = $i;') + g.writeln('\tint $it.val_var = $i;') g.stmts(it.stmts) g.writeln('}') } @@ -467,7 +467,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.write('for (int $i = 0; $i < ') g.expr(it.cond) g.writeln('.len; $i++) {') - g.write('$styp $it.val_var = (($styp*)') + g.write('\t$styp $it.val_var = (($styp*)') g.expr(it.cond) g.writeln('.data)[$i];') g.stmts(it.stmts) @@ -486,8 +486,8 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.expr(it.cond) g.writeln(');') g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; $idx++) {') - g.writeln('$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];') - g.write('$val_styp $it.val_var = (*($val_styp*)map_get3(') + g.writeln('\t$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];') + g.write('\t$val_styp $it.val_var = (*($val_styp*)map_get3(') g.expr(it.cond) g.writeln(', $key, &($val_styp[]){ $zero }));') g.stmts(it.stmts) @@ -641,36 +641,28 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } } else { - mut is_fixed_array_init := false - mut is_ident := false right_sym := g.table.get_type_symbol(assign_stmt.right_types[i]) + mut is_fixed_array_init := false match val { ast.ArrayInit { is_fixed_array_init = right_sym.kind == .array_fixed } - ast.Ident { - is_ident = true - } else {} } is_decl := assign_stmt.op == .decl_assign + g.write('/*assign_stmt*/') if is_decl { g.write('$styp ') } g.expr(ident) - if g.autofree && right_sym.kind == .array && is_ident { - // `arr1 = arr2` => `arr1 = arr2.clone()` - g.write(' = array_clone(&') - g.expr(val) - g.write(')') + if g.autofree && right_sym.kind in [.array, .string] { + if g.gen_clone_assignment(val, right_sym, true) { + g.writeln(';') + // g.expr_var_name = '' + return + } } - else if g.autofree && right_sym.kind == .string && is_ident { - // `str1 = str2` => `str1 = str2.clone()` - g.write(' = string_clone(') - g.expr(val) - g.write(')') - } - else if !is_fixed_array_init { + if !is_fixed_array_init { g.write(' = ') if !is_decl { g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ) @@ -692,6 +684,40 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } } +fn (g mut Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool { + mut is_ident := false + match val { + ast.Ident { + is_ident = true + } + ast.SelectorExpr { + is_ident = true + } + else { + return false + } + } + if g.autofree && right_sym.kind == .array && is_ident { + // `arr1 = arr2` => `arr1 = arr2.clone()` + if add_eq { + g.write('=') + } + g.write(' array_clone(&') + g.expr(val) + g.write(')') + } + else if g.autofree && right_sym.kind == .string && is_ident { + if add_eq { + g.write('=') + } + // `str1 = str2` => `str1 = str2.clone()` + g.write(' string_clone(') + g.expr(val) + g.write(')') + } + return true +} + fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { if it.is_c { // || it.no_body { @@ -1173,7 +1199,18 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { g.write(', ') } g.is_assign_lhs = false - g.expr_with_cast(node.val, node.right_type, node.left_type) + right_sym := g.table.get_type_symbol(node.right_type) + // left_sym := g.table.get_type_symbol(node.left_type) + mut cloned := false + // !g.is_array_set + if g.autofree && right_sym.kind in [.array, .string] { + if g.gen_clone_assignment(node.val, right_sym, false) { + cloned = true + } + } + if !cloned { + g.expr_with_cast(node.val, node.right_type, node.left_type) + } if g.is_array_set { g.write(' })') g.is_array_set = false @@ -1397,7 +1434,7 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) { ast.Type { it_type := g.typ(it.typ) // g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it') - g.write('$it_type* it = ($it_type*)') + g.write('\t$it_type* it = ($it_type*)') g.expr(node.cond) g.writeln('.obj; // ST it') } @@ -2194,53 +2231,64 @@ fn (g mut Gen) call_expr(node ast.CallExpr) { g.write('$styp $tmp_opt = ') } if node.is_method { - // TODO: there are still due to unchecked exprs (opt/some fn arg) - if node.left_type == 0 { - verror('method receiver type is 0, this means there are some uchecked exprs') + g.method_call(node) + } + else { + g.fn_call(node) + } + if gen_or { + g.or_block(tmp_opt, node.or_block.stmts, node.return_type) + } +} + +fn (g mut Gen) method_call(node ast.CallExpr) { + // TODO: there are still due to unchecked exprs (opt/some fn arg) + if node.left_type == 0 { + verror('method receiver type is 0, this means there are some uchecked exprs') + } + typ_sym := g.table.get_type_symbol(node.receiver_type) + // rec_sym := g.table.get_type_symbol(node.receiver_type) + mut receiver_name := typ_sym.name + if typ_sym.kind == .array && node.name == 'filter' { + g.gen_filter(node) + return + } + if typ_sym.kind == .array && node.name in + // TODO performance, detect `array` method differently + ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', + // + 'first', 'last', 'clone', 'reverse', 'slice'] { + // && rec_sym.name == 'array' { + // && rec_sym.name == 'array' && receiver_name.starts_with('array') { + // `array_byte_clone` => `array_clone` + receiver_name = 'array' + if node.name in ['last', 'first'] { + return_type_str := g.typ(node.return_type) + g.write('*($return_type_str*)') } - typ_sym := g.table.get_type_symbol(node.receiver_type) - // rec_sym := g.table.get_type_symbol(node.receiver_type) - mut receiver_name := typ_sym.name - if typ_sym.kind == .array && node.name == 'filter' { - g.gen_filter(node) - return - } - if typ_sym.kind == .array && node.name in - // TODO performance, detect `array` method differently - ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', - // - 'first', 'last', 'clone', 'reverse', 'slice'] { - // && rec_sym.name == 'array' { - // && rec_sym.name == 'array' && receiver_name.starts_with('array') { - // `array_byte_clone` => `array_clone` - receiver_name = 'array' - if node.name in ['last', 'first'] { - return_type_str := g.typ(node.return_type) - g.write('*($return_type_str*)') - } - } - name := '${receiver_name}_$node.name'.replace('.', '__') - // if node.receiver_type != 0 { - // g.write('/*${g.typ(node.receiver_type)}*/') - // g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/') - // } - g.write('${name}(') - if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) { - // The receiver is a reference, but the caller provided a value - // Add `&` automatically. - // TODO same logic in call_args() - g.write('&') - } - else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) { - g.write('/*rec*/*') - } - g.expr(node.left) - is_variadic := node.exp_arg_types.len > 0 && table.type_is_variadic(node.exp_arg_types[node.exp_arg_types.len - 1]) - if node.args.len > 0 || is_variadic { - g.write(', ') - } - // ///////// - /* + } + name := '${receiver_name}_$node.name'.replace('.', '__') + // if node.receiver_type != 0 { + // g.write('/*${g.typ(node.receiver_type)}*/') + // g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/') + // } + g.write('${name}(') + if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) { + // The receiver is a reference, but the caller provided a value + // Add `&` automatically. + // TODO same logic in call_args() + g.write('&') + } + else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) { + g.write('/*rec*/*') + } + g.expr(node.left) + is_variadic := node.exp_arg_types.len > 0 && table.type_is_variadic(node.exp_arg_types[node.exp_arg_types.len - 1]) + if node.args.len > 0 || is_variadic { + g.write(', ') + } + // ///////// + /* if name.contains('subkeys') { println('call_args $name $node.arg_types.len') for t in node.arg_types { @@ -2250,23 +2298,27 @@ fn (g mut Gen) call_expr(node ast.CallExpr) { println('') } */ - // /////// - g.call_args(node.args, node.exp_arg_types) - g.write(')') + // /////// + g.call_args(node.args, node.exp_arg_types) + g.write(')') + // if node.or_block.stmts.len > 0 { + // g.or_block(node.or_block.stmts, node.return_type) + // } +} + +fn (g mut Gen) fn_call(node ast.CallExpr) { + mut name := node.name + is_print := name == 'println' + if node.is_c { + // Skip "C." + g.is_c_call = true + name = name[2..].replace('.', '__') } else { - mut name := node.name - is_print := name == 'println' - if node.is_c { - // Skip "C." - g.is_c_call = true - name = name[2..].replace('.', '__') - } - else { - name = c_name(name) - } - // Generate tmp vars for values that have to be freed. - /* + name = c_name(name) + } + // Generate tmp vars for values that have to be freed. + /* mut tmps := []string for arg in node.args { if arg.typ == table.string_type_idx || is_print { @@ -2279,43 +2331,42 @@ fn (g mut Gen) call_expr(node ast.CallExpr) { } */ - if is_print && node.args[0].typ != table.string_type_idx { - typ := node.args[0].typ - mut styp := g.typ(typ) - sym := g.table.get_type_symbol(typ) - if !sym.has_method('str') && !(int(typ) in g.str_types) { - // Generate an automatic str() method if this type doesn't have it already - if table.type_is_ptr(typ) { - styp = styp.replace('*', '') - } - g.str_types << typ - g.definitions.writeln('string ${styp}_str($styp* x) { return tos3("TODO_str"); }') - } - if g.autofree && !table.type_is_optional(typ) { - tmp := g.new_tmp_var() - // tmps << tmp - g.write('string $tmp = ${styp}_str(') - g.expr(node.args[0].expr) - g.writeln('); println($tmp); string_free($tmp); //MEM2 $styp') - } - else { - // `println(int_str(10))` - // sym := g.table.get_type_symbol(node.args[0].typ) - g.write('println(${styp}_str(') - g.expr(node.args[0].expr) - g.write('))') + if is_print && node.args[0].typ != table.string_type_idx { + typ := node.args[0].typ + mut styp := g.typ(typ) + sym := g.table.get_type_symbol(typ) + if !sym.has_method('str') && !(int(typ) in g.str_types) { + // Generate an automatic str() method if this type doesn't have it already + if table.type_is_ptr(typ) { + styp = styp.replace('*', '') } + g.str_types << typ + g.definitions.writeln('string ${styp}_str($styp* x) { return tos3("TODO_str"); }') + } + if g.autofree && !table.type_is_optional(typ) { + tmp := g.new_tmp_var() + // tmps << tmp + g.write('string $tmp = ${styp}_str(') + g.expr(node.args[0].expr) + g.writeln('); println($tmp); string_free($tmp); //MEM2 $styp') } else { - g.write('${name}(') - g.call_args(node.args, node.exp_arg_types) - g.write(')') + // `println(int_str(10))` + // sym := g.table.get_type_symbol(node.args[0].typ) + g.write('println(${styp}_str(') + g.expr(node.args[0].expr) + g.write('))') } - g.is_c_call = false } - if gen_or { - g.or_block(tmp_opt, node.or_block.stmts, node.return_type) + else { + g.write('${name}(') + g.call_args(node.args, node.exp_arg_types) + g.write(')') } + // if node.or_block.stmts.len > 0 { + // g.or_block(node.or_block.stmts, node.return_type) + // } + g.is_c_call = false } // If user is accessing the return value eg. in assigment, pass the variable name. diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 75238cd5a1..b051215243 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -26,10 +26,10 @@ fn (p mut Parser) comp_if() ast.CompIf { // `$if os {` for a different target, skip everything inside // to avoid compilation errors (like including or calling WinAPI fns // on non-Windows systems) - if ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c { + if false && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c { skip_os = true p.check(.lcbr) - //p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os') + // p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os') mut stack := 1 for { if p.tok.kind == .key_return { @@ -75,7 +75,7 @@ fn (p mut Parser) comp_if() ast.CompIf { } const ( -todo_delete_me = pref.OS.linux // TODO import warning bug + todo_delete_me = pref.OS.linux // TODO import warning bug ) fn os_from_string(os string) pref.OS { diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 8535b952f8..0b253dfe5f 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -70,9 +70,10 @@ pub fn (p mut Parser) parse_multi_return_type() table.Type { pub fn (p mut Parser) parse_fn_type(name string) table.Type { // p.warn('parse fn') p.check(.key_fn) - args, is_variadic := p.fn_args() + line_nr := p.tok.line_nr + args,is_variadic := p.fn_args() mut return_type := table.void_type - if p.tok.kind.is_start_of_type() { + if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() { return_type = p.parse_type() } func := table.Fn{ @@ -96,7 +97,7 @@ pub fn (p mut Parser) parse_type() table.Type { mut nr_muls := 0 for p.tok.kind in [.and, .amp] { if p.tok.kind == .and { - nr_muls+=2 + nr_muls += 2 } else { nr_muls++ diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index e71b5d528d..d854ade247 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1520,6 +1520,13 @@ fn (p mut Parser) struct_decl() ast.StructDecl { field_name := p.check_name() // p.warn('field $field_name') typ := p.parse_type() + /* + if name == '_net_module_s' { + s := p.table.get_type_symbol(typ) + println('XXXX' + s.str()) + } + */ + // Default value if p.tok.kind == .assign { p.next()