parser/cgen: interface <<; `any` type
							parent
							
								
									2a016d03ac
								
							
						
					
					
						commit
						de749e9d3b
					
				|  | @ -391,7 +391,7 @@ pub fn (mut c Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { | |||
| 				// `array << elm`
 | ||||
| 				c.fail_if_immutable(infix_expr.left) | ||||
| 				// the expressions have different types (array_x and x)
 | ||||
| 				if c.table.check(c.table.value_type(left_type), right_type) { | ||||
| 				if c.table.check(right_type, c.table.value_type(left_type)) { // , right_type) {
 | ||||
| 					// []T << T
 | ||||
| 					return table.void_type | ||||
| 				} | ||||
|  | @ -400,7 +400,7 @@ pub fn (mut c Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { | |||
| 					return table.void_type | ||||
| 				} | ||||
| 				s := left.name.replace('array_', '[]') | ||||
| 				c.error('cannot append `$right.name` to `$s', infix_expr.right.position()) | ||||
| 				c.error('cannot append `$right.name` to `$s`', infix_expr.right.position()) | ||||
| 				return table.void_type | ||||
| 			} else if !left.is_int() { | ||||
| 				c.error('cannot shift type $right.name into non-integer type $left.name', infix_expr.left.position()) | ||||
|  |  | |||
|  | @ -1470,7 +1470,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { | |||
| 			g.write('array_push(&') | ||||
| 			g.expr(node.left) | ||||
| 			g.write(', &($elem_type_str[]){ ') | ||||
| 			elem_sym := g.table.get_type_symbol(info.elem_type) | ||||
| 			if elem_sym.kind == .interface_ { | ||||
| 				g.interface_call(node.right_type, info.elem_type) | ||||
| 			} | ||||
| 			g.expr_with_cast(node.right, node.right_type, info.elem_type) | ||||
| 			if elem_sym.kind == .interface_ { | ||||
| 				g.write(')') | ||||
| 			} | ||||
| 			g.write(' })') | ||||
| 		} | ||||
| 	} else if (node.left_type == node.right_type) && node.left_type.is_float() && node.op in | ||||
|  |  | |||
|  | @ -176,6 +176,7 @@ pub const ( | |||
| 	ustring_type_idx = 19 | ||||
| 	array_type_idx   = 20 | ||||
| 	map_type_idx     = 21 | ||||
| 	any_type_idx     = 22 | ||||
| ) | ||||
| 
 | ||||
| pub const ( | ||||
|  | @ -220,6 +221,7 @@ pub const ( | |||
| 	ustring_type = new_type(ustring_type_idx) | ||||
| 	array_type   = new_type(array_type_idx) | ||||
| 	map_type     = new_type(map_type_idx) | ||||
| 	any_type     = new_type(any_type_idx) | ||||
| ) | ||||
| 
 | ||||
| pub const ( | ||||
|  | @ -227,7 +229,7 @@ pub const ( | |||
| 		'u16', | ||||
| 		'u32', | ||||
| 		'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed', | ||||
| 		'map', 'struct', | ||||
| 		'map', 'any', 'struct', | ||||
| 		'mapnode', 'size_t'] | ||||
| ) | ||||
| 
 | ||||
|  | @ -270,6 +272,7 @@ pub enum Kind { | |||
| 	array | ||||
| 	array_fixed | ||||
| 	map | ||||
| 	any | ||||
| 	struct_ | ||||
| 	multi_return | ||||
| 	sum_type | ||||
|  | @ -427,6 +430,10 @@ pub fn (mut t Table) register_builtin_type_symbols() { | |||
| 		kind: .map | ||||
| 		name: 'map' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .any | ||||
| 		name: 'any' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .size_t | ||||
| 		name: 'size_t' | ||||
|  | @ -466,6 +473,7 @@ pub fn (t &TypeSymbol) is_number() bool { | |||
| 	return t.is_int() || t.is_float() | ||||
| } | ||||
| 
 | ||||
| // for debugging/errors only, perf is not an issue
 | ||||
| pub fn (k Kind) str() string { | ||||
| 	k_str := match k { | ||||
| 		.placeholder { 'placeholder' } | ||||
|  | @ -496,6 +504,7 @@ pub fn (k Kind) str() string { | |||
| 		.sum_type { 'sum_type' } | ||||
| 		.alias { 'alias' } | ||||
| 		.enum_ { 'enum' } | ||||
| 		.any { 'any' } | ||||
| 		else { 'unknown' } | ||||
| 	} | ||||
| 	return k_str | ||||
|  | @ -535,7 +544,7 @@ pub: | |||
| 	foo string | ||||
| } | ||||
| 
 | ||||
| // NB: FExpr here is a actually an ast.Expr . 
 | ||||
| // NB: FExpr here is a actually an ast.Expr .
 | ||||
| // It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe()
 | ||||
| // That hack is needed to break an import cycle between v.ast and v.table .
 | ||||
| type FExpr = voidptr | byteptr | ||||
|  |  | |||
|  | @ -469,6 +469,9 @@ pub fn (t &Table) check(got, expected Type) bool { | |||
| 	if exp_idx == voidptr_type_idx || got_idx == voidptr_type_idx { | ||||
| 		return true | ||||
| 	} | ||||
| 	if exp_idx == any_type_idx || got_idx == any_type_idx { | ||||
| 		return true | ||||
| 	} | ||||
| 	if (exp_idx in pointer_type_idxs || exp_idx in number_type_idxs) && (got_idx in pointer_type_idxs || | ||||
| 		got_idx in number_type_idxs) { | ||||
| 		return true | ||||
|  | @ -485,7 +488,7 @@ pub fn (t &Table) check(got, expected Type) bool { | |||
| 	// # NOTE: use symbols from this point on for perf
 | ||||
| 	got_type_sym := t.get_type_symbol(got) | ||||
| 	exp_type_sym := t.get_type_symbol(expected) | ||||
| 	//
 | ||||
| 	// Handle expected interface
 | ||||
| 	if exp_type_sym.kind == .interface_ { | ||||
| 		mut info := exp_type_sym.info as Interface | ||||
| 		// println('gen_types before')
 | ||||
|  | @ -498,6 +501,13 @@ pub fn (t &Table) check(got, expected Type) bool { | |||
| 		// println(info.gen_types)
 | ||||
| 		return true | ||||
| 	} | ||||
| 	// Handle expected interface array
 | ||||
| 	/* | ||||
| 	if exp_type_sym.kind == .array && t.get_type_symbol(t.value_type(exp_idx)).kind == .interface_ { | ||||
| 		return true | ||||
| 	} | ||||
| 	*/ | ||||
| 	//
 | ||||
| 	if exp_type_sym.kind == .function && got_type_sym.kind == .int { | ||||
| 		// TODO temporary
 | ||||
| 		// fn == 0
 | ||||
|  |  | |||
|  | @ -91,3 +91,11 @@ interface Speaker { | |||
| 	speak() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn test_interface_array() { | ||||
| 	mut animals := []Speaker{} | ||||
| 	animals = [ Cat{}, Dog{} ] | ||||
| 	animals << Cat{} | ||||
| 	assert true | ||||
| 	assert animals.len == 3 | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue