cgen: fix &string cast; vfmt fixes
							parent
							
								
									4aedef367c
								
							
						
					
					
						commit
						6bbd1943dd
					
				|  | @ -43,12 +43,12 @@ NB: A V string should be/is immutable from the point of view of | |||
| 
 | ||||
| 
 | ||||
| pub struct string { | ||||
| 	// mut:
 | ||||
| 	// hash_cache int
 | ||||
| pub: | ||||
| 	str byteptr // points to a C style 0 terminated string of bytes.
 | ||||
| 	len int // the length of the .str field, excluding the ending 0 byte. It is always equal to strlen(.str).
 | ||||
| } | ||||
| 	// mut:
 | ||||
| 	// hash_cache int
 | ||||
| 
 | ||||
| pub struct ustring { | ||||
| pub: | ||||
|  | @ -166,8 +166,8 @@ pub fn (s string) replace(rep, with string) string { | |||
| 	mut cur_idx := idxs[idx_pos] | ||||
| 	mut b_i := 0 | ||||
| 	for i := 0; i < s.len; i++ { | ||||
| 		// Reached the location of rep, replace it with "with"
 | ||||
| 		if i == cur_idx { | ||||
| 			// Reached the location of rep, replace it with "with"
 | ||||
| 			for j in 0..with.len { | ||||
| 				b[b_i] = with[j] | ||||
| 				b_i++ | ||||
|  | @ -180,8 +180,8 @@ pub fn (s string) replace(rep, with string) string { | |||
| 				cur_idx = idxs[idx_pos] | ||||
| 			} | ||||
| 		} | ||||
| 		// Rep doesnt start here, just copy
 | ||||
| 		else { | ||||
| 			// Rep doesnt start here, just copy
 | ||||
| 			b[b_i] = s[i] | ||||
| 			b_i++ | ||||
| 		} | ||||
|  | @ -263,8 +263,8 @@ pub fn (s string) replace_each(vals []string) string { | |||
| 	mut cur_idx := idxs[idx_pos] | ||||
| 	mut b_i := 0 | ||||
| 	for i := 0; i < s.len; i++ { | ||||
| 		// Reached the location of rep, replace it with "with"
 | ||||
| 		if i == cur_idx.idx { | ||||
| 			// Reached the location of rep, replace it with "with"
 | ||||
| 			rep := vals[cur_idx.val_idx] | ||||
| 			with := vals[cur_idx.val_idx + 1] | ||||
| 			for j in 0..with.len { | ||||
|  | @ -279,8 +279,8 @@ pub fn (s string) replace_each(vals []string) string { | |||
| 				cur_idx = idxs[idx_pos] | ||||
| 			} | ||||
| 		} | ||||
| 		// Rep doesnt start here, just copy
 | ||||
| 		else { | ||||
| 			// Rep doesnt start here, just copy
 | ||||
| 			b[b_i] = s.str[i] | ||||
| 			b_i++ | ||||
| 		} | ||||
|  |  | |||
|  | @ -265,6 +265,7 @@ pub struct GlobalDecl { | |||
| pub: | ||||
| 	name string | ||||
| 	expr Expr | ||||
| 	has_expr bool | ||||
| mut: | ||||
| 	typ  table.Type | ||||
| } | ||||
|  |  | |||
|  | @ -139,7 +139,8 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { | |||
| 					continue | ||||
| 				} | ||||
| 				if table.type_is_ptr(field.typ) { | ||||
| 					c.warn('reference field `${typ_sym.name}.${field.name}` must be initialized', struct_init.pos) | ||||
| 					c.warn('reference field `${typ_sym.name}.${field.name}` must be initialized',  | ||||
| 						struct_init.pos) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | @ -212,7 +213,7 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) { | |||
| 	if !c.table.check(right_type, left_type) { | ||||
| 		left_type_sym := c.table.get_type_symbol(left_type) | ||||
| 		right_type_sym := c.table.get_type_symbol(right_type) | ||||
| 		c.error('cannot assign $right_type_sym.name to $left_type_sym.name', assign_expr.pos) | ||||
| 		c.error('cannot assign `$right_type_sym.name` to `$left_type_sym.name`', assign_expr.pos) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -224,8 +225,8 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { | |||
| 		left_type_sym := c.table.get_type_symbol(left_type) | ||||
| 		method_name := call_expr.name | ||||
| 		// TODO: remove this for actual methods, use only for compiler magic
 | ||||
| 		if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse', 'map',  | ||||
| 			'slice'] { | ||||
| 		if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse',  | ||||
| 			'map', 'slice'] { | ||||
| 			if method_name in ['filter', 'map'] { | ||||
| 				array_info := left_type_sym.info as table.Array | ||||
| 				mut scope := c.file.scope.innermost(call_expr.pos.pos) | ||||
|  | @ -252,7 +253,8 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { | |||
| 		} | ||||
| 		if method := c.table.type_find_method(left_type_sym, method_name) { | ||||
| 			no_args := method.args.len - 1 | ||||
| 			min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 } | ||||
| 			min_required_args := method.args.len - if method.is_variadic && method.args.len >  | ||||
| 				1 { 2 } else { 1 } | ||||
| 			if call_expr.args.len < min_required_args { | ||||
| 				c.error('too few arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $min_required_args)',  | ||||
| 					call_expr.pos) | ||||
|  | @ -479,7 +481,8 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) { | |||
| 		return | ||||
| 	} | ||||
| 	if return_stmt.exprs.len > 0 && c.fn_return_type == table.void_type { | ||||
| 		c.error('too many arguments to return, current function does not return anything', return_stmt.pos) | ||||
| 		c.error('too many arguments to return, current function does not return anything',  | ||||
| 			return_stmt.pos) | ||||
| 		return | ||||
| 	} | ||||
| 	expected_type := c.fn_return_type | ||||
|  | @ -542,7 +545,8 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) { | |||
| 				if !c.table.check(val_type, var_type) { | ||||
| 					val_type_sym := c.table.get_type_symbol(val_type) | ||||
| 					var_type_sym := c.table.get_type_symbol(var_type) | ||||
| 					c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos) | ||||
| 					c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`',  | ||||
| 						assign_stmt.pos) | ||||
| 				} | ||||
| 			} | ||||
| 			ident_var_info.typ = val_type | ||||
|  | @ -568,7 +572,8 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) { | |||
| 				if !c.table.check(val_type, var_type) { | ||||
| 					val_type_sym := c.table.get_type_symbol(val_type) | ||||
| 					var_type_sym := c.table.get_type_symbol(var_type) | ||||
| 					c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos) | ||||
| 					c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`',  | ||||
| 						assign_stmt.pos) | ||||
| 				} | ||||
| 			} | ||||
| 			ident_var_info.typ = val_type | ||||
|  | @ -1181,7 +1186,8 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type { | |||
| 		// index_type_sym.kind != .enum_) {
 | ||||
| 		if typ_sym.kind in [.array, .array_fixed] && !(table.is_number(index_type) || index_type_sym.kind ==  | ||||
| 			.enum_) { | ||||
| 			c.error('non-integer index `$index_type_sym.name` (array type `$typ_sym.name`)', node.pos) | ||||
| 			c.error('non-integer index `$index_type_sym.name` (array type `$typ_sym.name`)',  | ||||
| 				node.pos) | ||||
| 		} else if typ_sym.kind == .map && table.type_idx(index_type) != table.string_type_idx { | ||||
| 			c.error('non-string map index (map type `$typ_sym.name`)', node.pos) | ||||
| 		} | ||||
|  | @ -1252,12 +1258,14 @@ pub fn (c mut Checker) map_init(node mut ast.MapInit) table.Type { | |||
| 		if !c.table.check(key_type, key0_type) { | ||||
| 			key0_type_sym := c.table.get_type_symbol(key0_type) | ||||
| 			key_type_sym := c.table.get_type_symbol(key_type) | ||||
| 			c.error('map init: cannot use `$key_type_sym.name` as `$key0_type_sym` for map key', node.pos) | ||||
| 			c.error('map init: cannot use `$key_type_sym.name` as `$key0_type_sym` for map key',  | ||||
| 				node.pos) | ||||
| 		} | ||||
| 		if !c.table.check(val_type, val0_type) { | ||||
| 			val0_type_sym := c.table.get_type_symbol(val0_type) | ||||
| 			val_type_sym := c.table.get_type_symbol(val_type) | ||||
| 			c.error('map init: cannot use `$val_type_sym.name` as `$val0_type_sym` for map value', node.pos) | ||||
| 			c.error('map init: cannot use `$val_type_sym.name` as `$val0_type_sym` for map value',  | ||||
| 				node.pos) | ||||
| 		} | ||||
| 	} | ||||
| 	map_type := table.new_type(c.table.find_or_register_map(key0_type, val0_type)) | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ import ( | |||
| 
 | ||||
| const ( | ||||
| 	tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t'] | ||||
| 	max_len = 100 | ||||
| 	max_len = 90 | ||||
| ) | ||||
| 
 | ||||
| struct Fmt { | ||||
|  | @ -137,6 +137,11 @@ fn (f mut Fmt) stmt(node ast.Stmt) { | |||
| 			} | ||||
| 			f.is_assign = false | ||||
| 		} | ||||
| 		ast.AssertStmt { | ||||
| 			f.write('assert ') | ||||
| 			f.expr(it.expr) | ||||
| 			f.writeln('') | ||||
| 		} | ||||
| 		ast.Attr { | ||||
| 			f.writeln('[$it.name]') | ||||
| 		} | ||||
|  | @ -159,6 +164,16 @@ fn (f mut Fmt) stmt(node ast.Stmt) { | |||
| 		ast.Comment { | ||||
| 			f.comment(it) | ||||
| 		} | ||||
| 		ast.CompIf { | ||||
| 			inversion := if it.is_not { '!' } else { '' } | ||||
| 			f.writeln('\$if ${inversion}${it.val} {') | ||||
| 			f.stmts(it.stmts) | ||||
| 			if it.has_else { | ||||
| 				f.writeln('} \$else {') | ||||
| 				f.stmts(it.else_stmts) | ||||
| 			} | ||||
| 			f.writeln('}') | ||||
| 		} | ||||
| 		ast.ConstDecl { | ||||
| 			if it.is_pub { | ||||
| 				f.write('pub ') | ||||
|  | @ -252,6 +267,14 @@ fn (f mut Fmt) stmt(node ast.Stmt) { | |||
| 			f.stmts(it.stmts) | ||||
| 			f.writeln('}') | ||||
| 		} | ||||
| 		ast.GlobalDecl { | ||||
| 			f.write('__global $it.name ') | ||||
| 			f.write(f.table.type_to_str(it.typ)) | ||||
| 			if it.has_expr { | ||||
| 				f.write(' = ') | ||||
| 				f.expr(it.expr) | ||||
| 			} | ||||
| 		} | ||||
| 		ast.GotoLabel { | ||||
| 			f.writeln('$it.name:') | ||||
| 		} | ||||
|  | @ -285,29 +308,13 @@ fn (f mut Fmt) stmt(node ast.Stmt) { | |||
| 		ast.StructDecl { | ||||
| 			f.struct_decl(it) | ||||
| 		} | ||||
| 		ast.UnsafeStmt { | ||||
| 			f.writeln('unsafe {') | ||||
| 			f.stmts(it.stmts) | ||||
| 			f.writeln('}') | ||||
| 		} | ||||
| 		ast.Import {} | ||||
| 		ast.TypeDecl { | ||||
| 			// already handled in f.imports
 | ||||
| 			f.type_decl(it) | ||||
| 		} | ||||
| 		ast.AssertStmt { | ||||
| 			f.write('assert ') | ||||
| 			f.expr(it.expr) | ||||
| 			f.writeln('') | ||||
| 		} | ||||
| 		ast.CompIf { | ||||
| 			inversion := if it.is_not { '!' } else { '' } | ||||
| 			f.writeln('\$if ${inversion}${it.val} {') | ||||
| 		ast.UnsafeStmt { | ||||
| 			f.writeln('unsafe {') | ||||
| 			f.stmts(it.stmts) | ||||
| 			if it.has_else { | ||||
| 				f.writeln('} \$else {') | ||||
| 				f.stmts(it.else_stmts) | ||||
| 			} | ||||
| 			f.writeln('}') | ||||
| 		} | ||||
| 		else { | ||||
|  | @ -575,6 +582,15 @@ fn (f mut Fmt) expr(node ast.Expr) { | |||
| 			f.write('.') | ||||
| 			f.write(it.field) | ||||
| 		} | ||||
| 		ast.SizeOf { | ||||
| 			f.writeln('sizeof(') | ||||
| 			if it.type_name != '' { | ||||
| 				f.writeln(it.type_name) | ||||
| 			} else { | ||||
| 				f.writeln(f.table.type_to_str(it.typ)) | ||||
| 			} | ||||
| 			f.writeln(')') | ||||
| 		} | ||||
| 		ast.StringLiteral { | ||||
| 			if it.val.contains("'") { | ||||
| 				f.write('"$it.val"') | ||||
|  |  | |||
|  | @ -15,10 +15,10 @@ import ( | |||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	c_reserved = ['delete', 'exit', 'unix', 'error', 'calloc', 'malloc', 'free', | ||||
| 		'panic', 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', | ||||
| 		'int', 'long', 'register', 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', | ||||
| 		'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'] | ||||
| 	c_reserved = ['delete', 'exit', 'unix', 'error', 'calloc', 'malloc', 'free', 'panic', 'auto',  | ||||
| 		'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register',  | ||||
| 		'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned',  | ||||
| 		'void', 'volatile', 'while'] | ||||
| ) | ||||
| 
 | ||||
| struct Gen { | ||||
|  | @ -58,8 +58,8 @@ mut: | |||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', | ||||
| 		'\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t'] | ||||
| 	tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',  | ||||
| 		'\t\t\t\t\t\t\t\t'] | ||||
| ) | ||||
| 
 | ||||
| pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string { | ||||
|  | @ -86,7 +86,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string | |||
| 		indent: -1 | ||||
| 	} | ||||
| 	g.init() | ||||
| 	//
 | ||||
| 	// 
 | ||||
| 	mut autofree_used := false | ||||
| 	for file in files { | ||||
| 		g.file = file | ||||
|  | @ -115,10 +115,10 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string | |||
| 	if g.is_test { | ||||
| 		g.write_tests_main() | ||||
| 	} | ||||
| 	//
 | ||||
| 	// 
 | ||||
| 	g.finish() | ||||
| 	return g.hashes() + g.includes.str() + g.typedefs.str() + g.typedefs2.str() + | ||||
| 		g.definitions.str() + g.gowrappers.str() + g.stringliterals.str() + g.out.str() | ||||
| 	return g.hashes() + g.includes.str() + g.typedefs.str() + g.typedefs2.str() + g.definitions.str() +  | ||||
| 		g.gowrappers.str() + g.stringliterals.str() + g.out.str() | ||||
| } | ||||
| 
 | ||||
| pub fn (g Gen) hashes() string { | ||||
|  | @ -141,7 +141,7 @@ pub fn (g mut Gen) init() { | |||
| 	g.write_sorted_types() | ||||
| 	g.write_multi_return_types() | ||||
| 	g.definitions.writeln('// end of definitions #endif') | ||||
| 	//
 | ||||
| 	// 
 | ||||
| 	g.stringliterals.writeln('') | ||||
| 	g.stringliterals.writeln('// >> string literal consts') | ||||
| 	g.stringliterals.writeln('void vinit_string_literals(){') | ||||
|  | @ -205,7 +205,7 @@ pub fn (g mut Gen) typ(t table.Type) string { | |||
| 	return styp | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // 
 | ||||
| pub fn (g mut Gen) write_typedef_types() { | ||||
| 	for typ in g.table.types { | ||||
| 		match typ.kind { | ||||
|  | @ -817,7 +817,7 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { | |||
| 		} | ||||
| 	} | ||||
| */ | ||||
| 	//
 | ||||
| 	// 
 | ||||
| 	g.fn_args(it.args, it.is_variadic) | ||||
| 	if it.no_body { | ||||
| 		// Just a function header.
 | ||||
|  | @ -1006,7 +1006,8 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 				g.out.go_back(1) | ||||
| 			} | ||||
| 			sym := g.table.get_type_symbol(it.typ) | ||||
| 			if sym.kind == .string { | ||||
| 			if sym.kind == .string && !table.type_is_ptr(it.typ) { | ||||
| 				// `string(x)` needs `tos()`, but not `&string(x)
 | ||||
| 				// `tos(str, len)`, `tos2(str)`
 | ||||
| 				if it.has_arg { | ||||
| 					g.write('tos(') | ||||
|  | @ -1135,8 +1136,7 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 				g.write('tos3("$escaped_val")') | ||||
| 				return | ||||
| 			} | ||||
| 			escaped_val := it.val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', | ||||
| 				'\\n']) | ||||
| 			escaped_val := it.val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n']) | ||||
| 			if g.is_c_call || it.is_c { | ||||
| 				// In C calls we have to generate C strings
 | ||||
| 				// `C.printf("hi")` => `printf("hi");`
 | ||||
|  | @ -1361,8 +1361,7 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { | |||
| 			g.expr(node.left) | ||||
| 			g.write(')') | ||||
| 		} | ||||
| 	} else if node.op == .left_shift && g.table.get_type_symbol(node.left_type).kind == | ||||
| 		.array { | ||||
| 	} else if node.op == .left_shift && g.table.get_type_symbol(node.left_type).kind == .array { | ||||
| 		// arr << val
 | ||||
| 		tmp := g.new_tmp_var() | ||||
| 		sym := g.table.get_type_symbol(node.left_type) | ||||
|  | @ -1452,7 +1451,7 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) { | |||
| 					// sum_type_str
 | ||||
| 				} else if type_sym.kind == .string { | ||||
| 					g.write('string_eq(') | ||||
| 					//
 | ||||
| 					// 
 | ||||
| 					g.expr(node.cond) | ||||
| 					g.write(', ') | ||||
| 					// g.write('string_eq($tmp, ')
 | ||||
|  | @ -1547,8 +1546,7 @@ fn (g mut Gen) if_expr(node ast.IfExpr) { | |||
| 	// one line ?:
 | ||||
| 	// TODO clean this up once `is` is supported
 | ||||
| 	// TODO: make sure only one stmt in each branch
 | ||||
| 	if node.is_expr && node.branches.len >= 2 && node.has_else && type_sym.kind != | ||||
| 		.void { | ||||
| 	if node.is_expr && node.branches.len >= 2 && node.has_else && type_sym.kind != .void { | ||||
| 		g.inside_ternary = true | ||||
| 		g.write('(') | ||||
| 		for i, branch in node.branches { | ||||
|  | @ -1952,7 +1950,7 @@ fn (g mut Gen) assoc(node ast.Assoc) { | |||
| } | ||||
| 
 | ||||
| fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { | ||||
| 	is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len - | ||||
| 	is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len -  | ||||
| 		1], .variadic) | ||||
| 	mut arg_no := 0 | ||||
| 	for arg in args { | ||||
|  | @ -1996,8 +1994,7 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { | |||
| 
 | ||||
| [inline] | ||||
| fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) { | ||||
| 	arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in | ||||
| 		table.pointer_type_idxs | ||||
| 	arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs | ||||
| 	expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs | ||||
| 	if arg.is_mut && !arg_is_ptr { | ||||
| 		g.write('&/*mut*/') | ||||
|  | @ -2134,7 +2131,7 @@ fn (g mut Gen) write_types(types []table.TypeSymbol) { | |||
| 					g.definitions.writeln('EMPTY_STRUCT_DECLARATION;') | ||||
| 				} | ||||
| 				// g.definitions.writeln('} $name;\n')
 | ||||
| 				//
 | ||||
| 				// 
 | ||||
| 				g.definitions.writeln('};\n') | ||||
| 			} | ||||
| 			table.Alias { | ||||
|  | @ -2201,8 +2198,8 @@ fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol { | |||
| 	// sort graph
 | ||||
| 	dep_graph_sorted := dep_graph.resolve() | ||||
| 	if !dep_graph_sorted.acyclic { | ||||
| 		verror('cgen.sort_structs(): the following structs form a dependency cycle:\n' + | ||||
| 			dep_graph_sorted.display_cycles() + '\nyou can solve this by making one or both of the dependant struct fields references, eg: field &MyStruct' + | ||||
| 		verror('cgen.sort_structs(): the following structs form a dependency cycle:\n' + dep_graph_sorted.display_cycles() +  | ||||
| 			'\nyou can solve this by making one or both of the dependant struct fields references, eg: field &MyStruct' +  | ||||
| 			'\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro') | ||||
| 	} | ||||
| 	// sort types
 | ||||
|  | @ -2339,8 +2336,8 @@ fn (g mut Gen) method_call(node ast.CallExpr) { | |||
| 		return | ||||
| 	} | ||||
| 	// TODO performance, detect `array` method differently
 | ||||
| 	if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', | ||||
| 		'push_many', 'trim', 'first', 'last', 'clone', 'reverse', 'slice'] { | ||||
| 	if typ_sym.kind == .array && node.name in ['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`
 | ||||
|  | @ -2365,7 +2362,7 @@ fn (g mut Gen) method_call(node ast.CallExpr) { | |||
| 		g.write('/*rec*/*') | ||||
| 	} | ||||
| 	g.expr(node.left) | ||||
| 	is_variadic := node.expected_arg_types.len > 0 && table.type_is(node.expected_arg_types[node.expected_arg_types.len - | ||||
| 	is_variadic := node.expected_arg_types.len > 0 && table.type_is(node.expected_arg_types[node.expected_arg_types.len -  | ||||
| 		1], .variadic) | ||||
| 	if node.args.len > 0 || is_variadic { | ||||
| 		g.write(', ') | ||||
|  | @ -2743,8 +2740,7 @@ pub fn (g mut Gen) write_tests_main() { | |||
| 	g.definitions.writeln('int g_test_fails = 0;') | ||||
| 	$if windows { | ||||
| 		g.writeln('int wmain() {') | ||||
| 	} | ||||
| 	$else { | ||||
| 	} $else { | ||||
| 		g.writeln('int main() {') | ||||
| 	} | ||||
| 	g.writeln('\t_vinit();') | ||||
|  |  | |||
|  | @ -627,7 +627,8 @@ pub fn (p mut Parser) name_expr() ast.Expr { | |||
| 		name_w_mod := p.prepend_mod(name) | ||||
| 		// type cast. TODO: finish
 | ||||
| 		// if name in table.builtin_type_names {
 | ||||
| 		if (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) && !(name in ['C.stat', 'C.sigaction']) { | ||||
| 		if (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) && !(name in ['C.stat',  | ||||
| 			'C.sigaction']) { | ||||
| 			// TODO handle C.stat()
 | ||||
| 			mut to_typ := p.parse_type() | ||||
| 			if p.is_amp { | ||||
|  | @ -660,9 +661,9 @@ pub fn (p mut Parser) name_expr() ast.Expr { | |||
| 			x := p.call_expr(is_c, mod)			// TODO `node,typ :=` should work
 | ||||
| 			node = x | ||||
| 		} | ||||
| 	} else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || is_c || (p.builtin_mod && p.tok.lit in  | ||||
| 		table.builtin_type_names)) && (p.tok.lit.len in [1, 2] || !p.tok.lit[p.tok.lit.len - 1].is_capital()) &&  | ||||
| 		!p.inside_match_case { | ||||
| 	} else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || is_c || (p.builtin_mod &&  | ||||
| 		p.tok.lit in table.builtin_type_names)) && (p.tok.lit.len in [1, 2] || !p.tok.lit[p.tok.lit.len -  | ||||
| 		1].is_capital()) && !p.inside_match_case { | ||||
| 		// || p.table.known_type(p.tok.lit)) {
 | ||||
| 		return p.struct_init(false)		// short_syntax: false
 | ||||
| 	} else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) { | ||||
|  | @ -1714,17 +1715,19 @@ fn (p mut Parser) hash() ast.HashStmt { | |||
| } | ||||
| 
 | ||||
| fn (p mut Parser) global_decl() ast.GlobalDecl { | ||||
| 	if !p.pref.translated && !p.pref.is_live && !p.builtin_mod && !p.pref.building_v && p.mod != 'ui' &&  | ||||
| 		p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals { | ||||
| 	if !p.pref.translated && !p.pref.is_live && !p.builtin_mod && !p.pref.building_v && p.mod !=  | ||||
| 		'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals { | ||||
| 		p.error('use `v --enable-globals ...` to enable globals') | ||||
| 	} | ||||
| 	p.next() | ||||
| 	name := p.check_name() | ||||
| 	// println(name)
 | ||||
| 	typ := p.parse_type() | ||||
| 	if p.tok.kind == .assign { | ||||
| 	mut expr := ast.Expr{} | ||||
| 	has_expr := p.tok.kind == .assign | ||||
| 	if has_expr { | ||||
| 		p.next() | ||||
| 		p.expr(0) | ||||
| 		expr = p.expr(0) | ||||
| 	} | ||||
| 	// p.genln(p.table.cgen_name_type_pair(name, typ))
 | ||||
| 	/* | ||||
|  | @ -1744,6 +1747,8 @@ fn (p mut Parser) global_decl() ast.GlobalDecl { | |||
| 	glob := ast.GlobalDecl{ | ||||
| 		name: name | ||||
| 		typ: typ | ||||
| 		has_expr: has_expr | ||||
| 		expr: expr | ||||
| 	} | ||||
| 	p.global_scope.register(name, glob) | ||||
| 	return glob | ||||
|  |  | |||
|  | @ -389,34 +389,36 @@ pub fn (t &Table) value_type(typ Type) Type { | |||
| 		// ...string => string
 | ||||
| 		return type_set(typ, .unset) | ||||
| 	} | ||||
| 	else if typ_sym.kind == .array { | ||||
| 	if typ_sym.kind == .array { | ||||
| 		// Check index type
 | ||||
| 		info := typ_sym.info as Array | ||||
| 		return info.elem_type | ||||
| 	} | ||||
| 	else if typ_sym.kind == .array_fixed { | ||||
| 	if typ_sym.kind == .array_fixed { | ||||
| 		info := typ_sym.info as ArrayFixed | ||||
| 		return info.elem_type | ||||
| 	} | ||||
| 	else if typ_sym.kind == .map { | ||||
| 	if typ_sym.kind == .map { | ||||
| 		info := typ_sym.info as Map | ||||
| 		return info.value_type | ||||
| 	} | ||||
| 	else if typ_sym.kind in [.byteptr, .string] { | ||||
| 	if typ_sym.kind == .string && table.type_is_ptr(typ) { | ||||
| 		// (&string)[i] => string
 | ||||
| 		return string_type | ||||
| 	} | ||||
| 	if typ_sym.kind in [.byteptr, .string] { | ||||
| 		return byte_type | ||||
| 	} | ||||
| 	else if type_is_ptr(typ) { | ||||
| 	if type_is_ptr(typ) { | ||||
| 		// byte* => byte
 | ||||
| 		// bytes[0] is a byte, not byte*
 | ||||
| 		return type_deref(typ) | ||||
| 	} | ||||
| 	else { | ||||
| 		// TODO: remove when map_string is removed
 | ||||
| 		if typ_sym.name == 'map_string' { | ||||
| 			return string_type | ||||
| 		} | ||||
| 		return void_type | ||||
| 	// TODO: remove when map_string is removed
 | ||||
| 	if typ_sym.name == 'map_string' { | ||||
| 		return string_type | ||||
| 	} | ||||
| 	return void_type | ||||
| } | ||||
| 
 | ||||
| pub fn (t &Table) check(got, expected Type) bool { | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| import os | ||||
| import time as t | ||||
| import crypto.sha256 as s2 | ||||
| import ( | ||||
| 	os | ||||
| 	time as t | ||||
| 	crypto.sha256 | ||||
| 	math | ||||
| 	log as l | ||||
| 	crypto.sha512 as s5 | ||||
| 	crypto.sha512 | ||||
| ) | ||||
| 
 | ||||
| struct TestAliasInStruct { | ||||
|  | @ -12,7 +12,9 @@ struct TestAliasInStruct { | |||
| } | ||||
| 
 | ||||
| fn test_import() { | ||||
| 	assert os.O_RDONLY == os.O_RDONLY && t.month_days[0] == t.month_days[0] && s2.size == s2.size && math.pi == math.pi && l.INFO == l.INFO && s5.size == s5.size | ||||
| 	info := l.Level.info | ||||
| 	assert os.O_RDONLY == os.O_RDONLY && t.month_days[0] == t.month_days[0] && sha256.size ==  | ||||
| 		sha256.size && math.pi == math.pi && info == .info && sha512.size == sha512.size | ||||
| } | ||||
| 
 | ||||
| fn test_alias_in_struct_field() { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue