cgen: error fixes; table: simplify; compiler tests
							parent
							
								
									b43ac2783d
								
							
						
					
					
						commit
						4b4c47461b
					
				|  | @ -107,6 +107,7 @@ pub: | |||
| 	mut_pos     int // mut:
 | ||||
| 	pub_pos     int // pub:
 | ||||
| 	pub_mut_pos int // pub mut:
 | ||||
| 	is_c        bool | ||||
| } | ||||
| 
 | ||||
| pub struct StructInit { | ||||
|  | @ -488,12 +489,12 @@ pub: | |||
| 
 | ||||
| pub struct AssignExpr { | ||||
| pub: | ||||
| 	op   token.Kind | ||||
| 	pos  token.Position | ||||
| 	left Expr | ||||
| 	val  Expr | ||||
| 	// mut:
 | ||||
| 	// left_type table.Type
 | ||||
| 	op        token.Kind | ||||
| 	pos       token.Position | ||||
| 	left      Expr | ||||
| 	val       Expr | ||||
| mut: | ||||
| 	left_type table.Type | ||||
| } | ||||
| 
 | ||||
| pub struct GotoLabel { | ||||
|  |  | |||
|  | @ -121,7 +121,6 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type | |||
| 		else {} | ||||
| 	} | ||||
| 	if c.is_amp { | ||||
| 		println('XAXAXAX') | ||||
| 		return table.type_to_ptr(struct_init.typ) | ||||
| 	} | ||||
| 	return struct_init.typ | ||||
|  | @ -153,7 +152,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { | |||
| 	return left_type | ||||
| } | ||||
| 
 | ||||
| fn (c mut Checker) assign_expr(assign_expr ast.AssignExpr) { | ||||
| fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) { | ||||
| 	match assign_expr.left { | ||||
| 		ast.Ident { | ||||
| 			if it.kind == .blank_ident { | ||||
|  | @ -164,6 +163,7 @@ fn (c mut Checker) assign_expr(assign_expr ast.AssignExpr) { | |||
| 	} | ||||
| 	left_type := c.expr(assign_expr.left) | ||||
| 	c.expected_type = left_type | ||||
| 	assign_expr.left_type = left_type | ||||
| 	// assign_expr.left_type = left_type
 | ||||
| 	// t := c.table.get_type_symbol(left_type)
 | ||||
| 	// println('setting exp type to $c.expected_type $t.name')
 | ||||
|  | @ -594,7 +594,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type { | |||
| 			return it.typ | ||||
| 		} | ||||
| 		ast.AssignExpr { | ||||
| 			c.assign_expr(it) | ||||
| 			c.assign_expr(mut it) | ||||
| 		} | ||||
| 		ast.Assoc { | ||||
| 			scope := c.file.scope.innermost(it.pos.pos) | ||||
|  |  | |||
|  | @ -58,6 +58,13 @@ pub fn (g &Gen) typ(t table.Type) string { | |||
| 	if nr_muls > 0 { | ||||
| 		styp += strings.repeat(`*`, nr_muls) | ||||
| 	} | ||||
| 	if styp.starts_with('C__') { | ||||
| 		styp = styp[3..] | ||||
| 	} | ||||
| 	if styp == 'stat' { | ||||
| 		// TODO perf and other C structs
 | ||||
| 		styp = 'struct stat' | ||||
| 	} | ||||
| 	return styp | ||||
| } | ||||
| 
 | ||||
|  | @ -286,7 +293,9 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 			// g.writeln('\t$field_type_sym.name $field.name;')
 | ||||
| 			// }
 | ||||
| 			// g.writeln('} $name;')
 | ||||
| 			g.typedefs.writeln('typedef struct $name $name;') | ||||
| 			if !it.is_c { | ||||
| 				g.typedefs.writeln('typedef struct $name $name;') | ||||
| 			} | ||||
| 		} | ||||
| 		ast.TypeDecl { | ||||
| 			g.writeln('// type') | ||||
|  | @ -302,6 +311,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 
 | ||||
| fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { | ||||
| 	// multi return
 | ||||
| 	// g.write('/*assign*/')
 | ||||
| 	if assign_stmt.left.len > assign_stmt.right.len { | ||||
| 		mut return_type := table.void_type | ||||
| 		match assign_stmt.right[0] { | ||||
|  | @ -399,6 +409,9 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { | |||
| 		if name.starts_with('_op_') { | ||||
| 			name = op_to_fn_name(name) | ||||
| 		} | ||||
| 		if name == 'exit' { | ||||
| 			name = 'v_exit' | ||||
| 		} | ||||
| 		// type_name := g.table.type_to_str(it.return_type)
 | ||||
| 		type_name := g.typ(it.return_type) | ||||
| 		g.write('$type_name ${name}(') | ||||
|  | @ -503,17 +516,30 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 		} | ||||
| 		ast.AssignExpr { | ||||
| 			g.is_assign_expr = true | ||||
| 			mut str_add := false | ||||
| 			if it.left_type == table.string_type_idx && it.op == .plus_assign { | ||||
| 				// str += str2 => `str = string_add(str, str2)`
 | ||||
| 				g.expr(it.left) | ||||
| 				g.write(' = string_add(') | ||||
| 				str_add = true | ||||
| 			} | ||||
| 			g.expr(it.left) | ||||
| 			// arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val`
 | ||||
| 			if !g.is_array_set { | ||||
| 			if !g.is_array_set && !str_add { | ||||
| 				g.write(' $it.op.str() ') | ||||
| 			} | ||||
| 			else if str_add { | ||||
| 				g.write(', ') | ||||
| 			} | ||||
| 			g.is_assign_expr = false | ||||
| 			g.expr(it.val) | ||||
| 			if g.is_array_set { | ||||
| 				g.write(' })') | ||||
| 				g.is_array_set = false | ||||
| 			} | ||||
| 			else if str_add { | ||||
| 				g.write(')') | ||||
| 			} | ||||
| 		} | ||||
| 		ast.Assoc { | ||||
| 			g.write('/* assoc */') | ||||
|  | @ -523,6 +549,9 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 		} | ||||
| 		ast.CallExpr { | ||||
| 			mut name := it.name.replace('.', '__') | ||||
| 			if name == 'exit' { | ||||
| 				name = 'v_exit' | ||||
| 			} | ||||
| 			if it.is_c { | ||||
| 				// Skip "C__"
 | ||||
| 				g.is_c_call = true | ||||
|  | @ -834,6 +863,9 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 				g.expr(it.exprs[i]) | ||||
| 				g.writeln(', ') | ||||
| 			} | ||||
| 			if it.fields.len == 0 { | ||||
| 				g.write('0') | ||||
| 			} | ||||
| 			g.write('}') | ||||
| 			if g.is_amp { | ||||
| 				g.write(', sizeof($styp))') | ||||
|  | @ -865,6 +897,7 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| } | ||||
| 
 | ||||
| fn (g mut Gen) infix_expr(node ast.InfixExpr) { | ||||
| 	// g.write('/*infix*/')
 | ||||
| 	// if it.left_type == table.string_type_idx {
 | ||||
| 	// g.write('/*$node.left_type str*/')
 | ||||
| 	// }
 | ||||
|  | @ -1103,6 +1136,9 @@ fn (g mut Gen) write_sorted_types() { | |||
| 
 | ||||
| fn (g mut Gen) write_types(types []table.TypeSymbol) { | ||||
| 	for typ in types { | ||||
| 		if typ.name.starts_with('C.') { | ||||
| 			continue | ||||
| 		} | ||||
| 		// sym := g.table.get_type_symbol(typ)
 | ||||
| 		match typ.info { | ||||
| 			table.Struct { | ||||
|  |  | |||
|  | @ -49,6 +49,8 @@ fn compare_texts(a, b, path string) bool { | |||
| 			println('${path}: got\n$a') | ||||
| 			println('${term_fail} ${i}') | ||||
| 			println(term.red('i=$i "$line_a" expected="$line_b"')) | ||||
| 			// println(lines_b[i + 1])
 | ||||
| 			// println(lines_b[i + 2])
 | ||||
| 			// exit(1)
 | ||||
| 			return false | ||||
| 		} | ||||
|  |  | |||
|  | @ -59,7 +59,7 @@ int main() { | |||
| 	println(int_str(localmod__pub_int_const)); | ||||
| 	int g = ((int)(3.0)); | ||||
| 	byte* bytes = ((byte*)(0)); | ||||
| 	User* user_ptr = (User*)memdup(&(User){}, sizeof(User)); | ||||
| 	User* user_ptr = (User*)memdup(&(User){0}, sizeof(User)); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -82,7 +82,7 @@ i < 10; i++) { | |||
| 	}); | ||||
| 	array_User users = new_array_from_c_array(1, 1, sizeof(array_User), (User[]){ | ||||
| 		(User){ | ||||
| 			}, | ||||
| 			0}, | ||||
| 	}); | ||||
| 	bool b = (*(bool*)array_get(bools, 0)); | ||||
| 	array_string mystrings = new_array_from_c_array(2, 2, sizeof(array_string), (string[]){ | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ void init_user() { | |||
| 
 | ||||
| User get_user() { | ||||
| 	User user = (User){ | ||||
| 	}; | ||||
| 	0}; | ||||
| 	return user; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ tos3(""), | |||
| 
 | ||||
| int main() { | ||||
| 	User user = (User){ | ||||
| }; | ||||
| 0}; | ||||
| 	user.age = 10; | ||||
| 	user.age++; | ||||
| 	user.name = tos3("bob"); | ||||
|  |  | |||
|  | @ -1440,6 +1440,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { | |||
| 		mut_pos: mut_pos | ||||
| 		pub_pos: pub_pos | ||||
| 		pub_mut_pos: pub_mut_pos | ||||
| 		is_c: is_c | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,469 +3,3 @@ | |||
| // that can be found in the LICENSE file.
 | ||||
| module table | ||||
| 
 | ||||
| import ( | ||||
| 	strings | ||||
| ) | ||||
| 
 | ||||
| pub type TypeInfo = Array | ArrayFixed | Map | Struct | 	 | ||||
| MultiReturn | Alias | Enum | SumType | Fn | ||||
| 
 | ||||
| pub struct TypeSymbol { | ||||
| pub: | ||||
| 	parent_idx int | ||||
| mut: | ||||
| 	info       TypeInfo | ||||
| 	kind       Kind | ||||
| 	name       string | ||||
| 	methods    []Fn | ||||
| 	// is_sum    bool
 | ||||
| } | ||||
| 
 | ||||
| pub const ( | ||||
| // primitive types
 | ||||
| 	void_type_idx = 1 | ||||
| 	voidptr_type_idx = 2 | ||||
| 	byteptr_type_idx = 3 | ||||
| 	charptr_type_idx = 4 | ||||
| 	i8_type_idx = 5 | ||||
| 	i16_type_idx = 6 | ||||
| 	int_type_idx = 7 | ||||
| 	i64_type_idx = 8 | ||||
| 	byte_type_idx = 9 | ||||
| 	u16_type_idx = 10 | ||||
| 	u32_type_idx = 11 | ||||
| 	u64_type_idx = 12 | ||||
| 	f32_type_idx = 13 | ||||
| 	f64_type_idx = 14 | ||||
| 	char_type_idx = 15 | ||||
| 	bool_type_idx = 16 | ||||
| 	none_type_idx = 17 | ||||
| 	// advanced / defined from v structs
 | ||||
| 	string_type_idx = 18 | ||||
| 	array_type_idx = 19 | ||||
| 	map_type_idx = 20 | ||||
| ) | ||||
| 
 | ||||
| pub const ( | ||||
| 	builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', | ||||
| 	'f32', 'f64', 'string', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'struct', | ||||
| 	'mapnode', 'ustring'] | ||||
| ) | ||||
| 
 | ||||
| pub struct MultiReturn { | ||||
| pub: | ||||
| 	name  string | ||||
| mut: | ||||
| 	types []Type | ||||
| } | ||||
| 
 | ||||
| pub enum Kind { | ||||
| 	placeholder | ||||
| 	void | ||||
| 	voidptr | ||||
| 	byteptr | ||||
| 	charptr | ||||
| 	i8 | ||||
| 	i16 | ||||
| 	int | ||||
| 	i64 | ||||
| 	byte | ||||
| 	u16 | ||||
| 	u32 | ||||
| 	u64 | ||||
| 	f32 | ||||
| 	f64 | ||||
| 	char | ||||
| 	bool | ||||
| 	none_ | ||||
| 	string | ||||
| 	array | ||||
| 	array_fixed | ||||
| 	map | ||||
| 	struct_ | ||||
| 	multi_return | ||||
| 	sum_type | ||||
| 	alias | ||||
| 	enum_ | ||||
| 	function | ||||
| } | ||||
| 
 | ||||
| pub fn (t &TypeSymbol) str() string { | ||||
| 	return t.name.replace('array_', '[]') | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) enum_info() Enum { | ||||
| 	match t.info { | ||||
| 		Enum { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.enum_info(): no enum info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) mr_info() MultiReturn { | ||||
| 	match t.info { | ||||
| 		MultiReturn { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) array_info() Array { | ||||
| 	match t.info { | ||||
| 		Array { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.array_info(): no array info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed { | ||||
| 	match t.info { | ||||
| 		ArrayFixed { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) map_info() Map { | ||||
| 	match t.info { | ||||
| 		Map { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.map_info(): no map info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| pub fn (t TypeSymbol) str() string { | ||||
| 	return t.name | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| pub fn (t mut Table) register_builtin_type_symbols() { | ||||
| 	// reserve index 0 so nothing can go there
 | ||||
| 	// save index check, 0 will mean not found
 | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .placeholder | ||||
| 		name: 'reserved_0' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .void | ||||
| 		name: 'void' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .voidptr | ||||
| 		name: 'voidptr' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .byteptr | ||||
| 		name: 'byteptr' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .charptr | ||||
| 		name: 'charptr' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .i8 | ||||
| 		name: 'i8' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .i16 | ||||
| 		name: 'i16' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .int | ||||
| 		name: 'int' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .i64 | ||||
| 		name: 'i64' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .byte | ||||
| 		name: 'byte' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .u16 | ||||
| 		name: 'u16' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .u32 | ||||
| 		name: 'u32' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .u64 | ||||
| 		name: 'u64' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .f32 | ||||
| 		name: 'f32' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .f64 | ||||
| 		name: 'f64' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .char | ||||
| 		name: 'char' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .bool | ||||
| 		name: 'bool' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .none_ | ||||
| 		name: 'none' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .string | ||||
| 		name: 'string' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .array | ||||
| 		name: 'array' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .map | ||||
| 		name: 'map' | ||||
| 	}) | ||||
| 	// TODO: remove. for v1 map compatibility
 | ||||
| 	map_string_string_idx := t.find_or_register_map(string_type, string_type) | ||||
| 	map_string_int_idx := t.find_or_register_map(string_type, int_type) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .alias | ||||
| 		name: 'map_string' | ||||
| 		parent_idx: map_string_string_idx | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .alias | ||||
| 		name: 'map_int' | ||||
| 		parent_idx: map_string_int_idx | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_int() bool { | ||||
| 	return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_float() bool { | ||||
| 	return t.kind in [.f32, .f64] | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_number() bool { | ||||
| 	return t.is_int() || t.is_float() | ||||
| } | ||||
| 
 | ||||
| pub fn (k Kind) str() string { | ||||
| 	k_str := match k { | ||||
| 		.placeholder{ | ||||
| 			'placeholder' | ||||
| 		} | ||||
| 		.void{ | ||||
| 			'void' | ||||
| 		} | ||||
| 		.voidptr{ | ||||
| 			'voidptr' | ||||
| 		} | ||||
| 		.charptr{ | ||||
| 			'charptr' | ||||
| 		} | ||||
| 		.byteptr{ | ||||
| 			'byteptr' | ||||
| 		} | ||||
| 		.struct_{ | ||||
| 			'struct' | ||||
| 		} | ||||
| 		.int{ | ||||
| 			'int' | ||||
| 		} | ||||
| 		.i8{ | ||||
| 			'i8' | ||||
| 		} | ||||
| 		.i16{ | ||||
| 			'i16' | ||||
| 		} | ||||
| 		.i64{ | ||||
| 			'i64' | ||||
| 		} | ||||
| 		.byte{ | ||||
| 			'byte' | ||||
| 		} | ||||
| 		.u16{ | ||||
| 			'u16' | ||||
| 		} | ||||
| 		.u32{ | ||||
| 			'u32' | ||||
| 		} | ||||
| 		.u64{ | ||||
| 			'u64' | ||||
| 		} | ||||
| 		.f32{ | ||||
| 			'f32' | ||||
| 		} | ||||
| 		.f64{ | ||||
| 			'f64' | ||||
| 		} | ||||
| 		.string{ | ||||
| 			'string' | ||||
| 		} | ||||
| 		.char{ | ||||
| 			'char' | ||||
| 		} | ||||
| 		.bool{ | ||||
| 			'bool' | ||||
| 		} | ||||
| 		.none_{ | ||||
| 			'none' | ||||
| 		} | ||||
| 		.array{ | ||||
| 			'array' | ||||
| 		} | ||||
| 		.array_fixed{ | ||||
| 			'array_fixed' | ||||
| 		} | ||||
| 		.map{ | ||||
| 			'map' | ||||
| 		} | ||||
| 		.multi_return{ | ||||
| 			'multi_return' | ||||
| 		} | ||||
| 		.sum_type{ | ||||
| 			'sum_type' | ||||
| 		} | ||||
| 		.alias{ | ||||
| 			'alias' | ||||
| 		} | ||||
| 		.enum_{ | ||||
| 			'enum' | ||||
| 		} | ||||
| 		else { | ||||
| 			'unknown'} | ||||
| 	} | ||||
| 	return k_str | ||||
| } | ||||
| 
 | ||||
| pub fn (kinds []Kind) str() string { | ||||
| 	mut kinds_str := '' | ||||
| 	for i, k in kinds { | ||||
| 		kinds_str += k.str() | ||||
| 		if i < kinds.len - 1 { | ||||
| 			kinds_str += '_' | ||||
| 		} | ||||
| 	} | ||||
| 	return kinds_str | ||||
| } | ||||
| 
 | ||||
| pub struct Struct { | ||||
| pub mut: | ||||
| 	fields []Field | ||||
| } | ||||
| 
 | ||||
| pub struct Enum { | ||||
| pub mut: | ||||
| 	vals []string | ||||
| } | ||||
| 
 | ||||
| pub struct Alias { | ||||
| pub: | ||||
| 	foo string | ||||
| } | ||||
| 
 | ||||
| pub struct Field { | ||||
| pub: | ||||
| 	name string | ||||
| mut: | ||||
| 	typ  Type | ||||
| } | ||||
| 
 | ||||
| pub struct Array { | ||||
| pub: | ||||
| 	nr_dims   int | ||||
| mut: | ||||
| 	elem_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct ArrayFixed { | ||||
| pub: | ||||
| 	nr_dims   int | ||||
| 	size      int | ||||
| mut: | ||||
| 	elem_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct Map { | ||||
| pub mut: | ||||
| 	key_type   Type | ||||
| 	value_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct SumType { | ||||
| pub: | ||||
| 	variants []Type | ||||
| } | ||||
| 
 | ||||
| pub fn (table &Table) type_to_str(t Type) string { | ||||
| 	sym := table.get_type_symbol(t) | ||||
| 	if sym.kind == .multi_return { | ||||
| 		mut res := '(' | ||||
| 		mr_info := sym.info as MultiReturn | ||||
| 		for i, typ in mr_info.types { | ||||
| 			res += table.type_to_str(typ) | ||||
| 			if i < mr_info.types.len - 1 { | ||||
| 				res += ', ' | ||||
| 			} | ||||
| 		} | ||||
| 		res += ')' | ||||
| 		return res | ||||
| 	} | ||||
| 	mut res := sym.name | ||||
| 	if sym.kind == .array { | ||||
| 		res = res.replace('array_', '[]') | ||||
| 	} | ||||
| 	else if sym.kind == .map { | ||||
| 		res = res.replace('map_string_', 'map[string]') | ||||
| 	} | ||||
| 	// mod.submod.submod2.Type => submod2.Type
 | ||||
| 	if res.contains('.') { | ||||
| 		vals := res.split('.') | ||||
| 		if vals.len > 2 { | ||||
| 			res = vals[vals.len - 2] + '.' + vals[vals.len - 1] | ||||
| 		} | ||||
| 	} | ||||
| 	if type_is_optional(t) { | ||||
| 		res = '?' + res | ||||
| 	} | ||||
| 	nr_muls := type_nr_muls(t) | ||||
| 	if nr_muls > 0 { | ||||
| 		res = strings.repeat(`&`, nr_muls) + res | ||||
| 	} | ||||
| 	/* | ||||
| 	if res.starts_with(cur_mod +'.') { | ||||
| 	res = res[cur_mod.len+1.. ] | ||||
| 	} | ||||
| 	*/ | ||||
| 
 | ||||
| 	return res | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,621 @@ | |||
| module table | ||||
| 
 | ||||
| import ( | ||||
| 	strings | ||||
| ) | ||||
| 
 | ||||
| pub type Type int | ||||
| 
 | ||||
| pub type TypeInfo = Array | ArrayFixed | Map | Struct | 	 | ||||
| MultiReturn | Alias | Enum | SumType | Fn | ||||
| 
 | ||||
| pub struct TypeSymbol { | ||||
| pub: | ||||
| 	parent_idx int | ||||
| mut: | ||||
| 	info       TypeInfo | ||||
| 	kind       Kind | ||||
| 	name       string | ||||
| 	methods    []Fn | ||||
| 	// is_sum    bool
 | ||||
| } | ||||
| 
 | ||||
| pub enum TypeExtra { | ||||
| 	unset | ||||
| 	optional | ||||
| 	variadic | ||||
| } | ||||
| 
 | ||||
| pub fn (types []Type) contains(typ Type) bool { | ||||
| 	for t in types { | ||||
| 		if int(typ) == int(t) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // return underlying TypeSymbol idx
 | ||||
| [inline] | ||||
| pub fn type_idx(t Type) int { | ||||
| 	return u16(t) & 0xffff | ||||
| } | ||||
| 
 | ||||
| // return nr_muls
 | ||||
| [inline] | ||||
| pub fn type_nr_muls(t Type) int { | ||||
| 	return (int(t)>>16) & 0xff | ||||
| } | ||||
| 
 | ||||
| // return true if pointer (nr_muls>0)
 | ||||
| [inline] | ||||
| pub fn type_is_ptr(t Type) bool { | ||||
| 	return type_nr_muls(t) > 0 // || t == voidptr_type_idx
 | ||||
| } | ||||
| // set nr_muls on Type and return it
 | ||||
| [inline] | ||||
| pub fn type_set_nr_muls(t Type, nr_muls int) Type { | ||||
| 	if nr_muls < 0 || nr_muls > 255 { | ||||
| 		panic('typ_set_nr_muls: nr_muls must be between 0 & 255') | ||||
| 	} | ||||
| 	return (int(type_extra(t))<<24) | (nr_muls<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| // increments nr_nuls on Type and return it
 | ||||
| [inline] | ||||
| pub fn type_to_ptr(t Type) Type { | ||||
| 	nr_muls := type_nr_muls(t) | ||||
| 	if nr_muls == 255 { | ||||
| 		panic('type_to_pre: nr_muls is already at max of 255') | ||||
| 	} | ||||
| 	return (int(type_extra(t))<<24) | ((nr_muls + 1)<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| // decrement nr_muls on Type and return it
 | ||||
| [inline] | ||||
| pub fn type_deref(t Type) Type { | ||||
| 	nr_muls := type_nr_muls(t) | ||||
| 	if nr_muls == 0 { | ||||
| 		panic('deref: type `$t` is not a pointer') | ||||
| 	} | ||||
| 	return (int(type_extra(t))<<24) | ((nr_muls - 1)<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| // return extra info
 | ||||
| [inline] | ||||
| pub fn type_extra(t Type) TypeExtra { | ||||
| 	return (int(t)>>24) & 0xff | ||||
| } | ||||
| 
 | ||||
| // set extra info
 | ||||
| [inline] | ||||
| pub fn type_set_extra(t Type, extra TypeExtra) Type { | ||||
| 	return (int(extra)<<24) | (type_nr_muls(t)<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_is_optional(t Type) bool { | ||||
| 	return type_extra(t) == .optional | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_to_optional(t Type) Type { | ||||
| 	return type_set_extra(t, .optional) | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_is_variadic(t Type) bool { | ||||
| 	return type_extra(t) == .variadic | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_to_variadic(t Type) Type { | ||||
| 	return type_set_extra(t, .variadic) | ||||
| } | ||||
| 
 | ||||
| // new type with idx of TypeSymbol, not pointer (nr_muls=0)
 | ||||
| [inline] | ||||
| pub fn new_type(idx int) Type { | ||||
| 	if idx < 1 || idx > 65536 { | ||||
| 		panic('new_type_id: idx must be between 1 & 65536') | ||||
| 	} | ||||
| 	return idx | ||||
| } | ||||
| 
 | ||||
| // return Type idx of TypeSymbol & specify if ptr (nr_muls)
 | ||||
| [inline] | ||||
| pub fn new_type_ptr(idx int, nr_muls int) Type { | ||||
| 	if idx < 1 || idx > 65536 { | ||||
| 		panic('typ_ptr: idx must be between 1 & 65536') | ||||
| 	} | ||||
| 	if nr_muls < 0 || nr_muls > 255 { | ||||
| 		panic('typ_ptr: nr_muls must be between 0 & 255') | ||||
| 	} | ||||
| 	return (nr_muls<<16) | u16(idx) | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| pub fn is_number(typ Type) bool { | ||||
| 	typ_sym := c.table.get_type_symbol(typ) | ||||
| 	return typ_sym.is_int() | ||||
| 	//idx := type_idx(typ)
 | ||||
| 	//return idx in [int_type_idx, byte_type_idx, u64_type_idx]
 | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| pub const ( | ||||
| // primitive types
 | ||||
| 	void_type_idx = 1 | ||||
| 	voidptr_type_idx = 2 | ||||
| 	byteptr_type_idx = 3 | ||||
| 	charptr_type_idx = 4 | ||||
| 	i8_type_idx = 5 | ||||
| 	i16_type_idx = 6 | ||||
| 	int_type_idx = 7 | ||||
| 	i64_type_idx = 8 | ||||
| 	byte_type_idx = 9 | ||||
| 	u16_type_idx = 10 | ||||
| 	u32_type_idx = 11 | ||||
| 	u64_type_idx = 12 | ||||
| 	f32_type_idx = 13 | ||||
| 	f64_type_idx = 14 | ||||
| 	char_type_idx = 15 | ||||
| 	bool_type_idx = 16 | ||||
| 	none_type_idx = 17 | ||||
| 	// advanced / defined from v structs
 | ||||
| 	string_type_idx = 18 | ||||
| 	array_type_idx = 19 | ||||
| 	map_type_idx = 20 | ||||
| ) | ||||
| 
 | ||||
| pub const ( | ||||
| 	number_idxs = [int_type_idx, byte_type_idx, u16_type_idx, i16_type_idx, i64_type_idx, u32_type_idx, u64_type_idx] | ||||
| ) | ||||
| 
 | ||||
| pub const ( | ||||
| 	void_type = new_type(void_type_idx) | ||||
| 	voidptr_type = new_type(voidptr_type_idx) | ||||
| 	byteptr_type = new_type(byteptr_type_idx) | ||||
| 	charptr_type = new_type(charptr_type_idx) | ||||
| 	i8_type = new_type(i8_type_idx) | ||||
| 	int_type = new_type(int_type_idx) | ||||
| 	i16_type = new_type(i16_type_idx) | ||||
| 	i64_type = new_type(i64_type_idx) | ||||
| 	byte_type = new_type(byte_type_idx) | ||||
| 	u16_type = new_type(u16_type_idx) | ||||
| 	u32_type = new_type(u32_type_idx) | ||||
| 	u64_type = new_type(u64_type_idx) | ||||
| 	f32_type = new_type(f32_type_idx) | ||||
| 	f64_type = new_type(f64_type_idx) | ||||
| 	char_type = new_type(char_type_idx) | ||||
| 	bool_type = new_type(bool_type_idx) | ||||
| 	none_type = new_type(none_type_idx) | ||||
| 	string_type = new_type(string_type_idx) | ||||
| 	array_type = new_type(array_type_idx) | ||||
| 	map_type = new_type(map_type_idx) | ||||
| ) | ||||
| 
 | ||||
| pub const ( | ||||
| 	builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', | ||||
| 	'f32', 'f64', 'string', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'struct', | ||||
| 	'mapnode', 'ustring'] | ||||
| ) | ||||
| 
 | ||||
| pub struct MultiReturn { | ||||
| pub: | ||||
| 	name  string | ||||
| mut: | ||||
| 	types []Type | ||||
| } | ||||
| 
 | ||||
| pub enum Kind { | ||||
| 	placeholder | ||||
| 	void | ||||
| 	voidptr | ||||
| 	byteptr | ||||
| 	charptr | ||||
| 	i8 | ||||
| 	i16 | ||||
| 	int | ||||
| 	i64 | ||||
| 	byte | ||||
| 	u16 | ||||
| 	u32 | ||||
| 	u64 | ||||
| 	f32 | ||||
| 	f64 | ||||
| 	char | ||||
| 	bool | ||||
| 	none_ | ||||
| 	string | ||||
| 	array | ||||
| 	array_fixed | ||||
| 	map | ||||
| 	struct_ | ||||
| 	multi_return | ||||
| 	sum_type | ||||
| 	alias | ||||
| 	enum_ | ||||
| 	function | ||||
| } | ||||
| 
 | ||||
| pub fn (t &TypeSymbol) str() string { | ||||
| 	return t.name.replace('array_', '[]') | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) enum_info() Enum { | ||||
| 	match t.info { | ||||
| 		Enum { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.enum_info(): no enum info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) mr_info() MultiReturn { | ||||
| 	match t.info { | ||||
| 		MultiReturn { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) array_info() Array { | ||||
| 	match t.info { | ||||
| 		Array { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.array_info(): no array info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed { | ||||
| 	match t.info { | ||||
| 		ArrayFixed { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) map_info() Map { | ||||
| 	match t.info { | ||||
| 		Map { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('TypeSymbol.map_info(): no map info for type: $t.name') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| pub fn (t TypeSymbol) str() string { | ||||
| 	return t.name | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| pub fn (t mut Table) register_builtin_type_symbols() { | ||||
| 	// reserve index 0 so nothing can go there
 | ||||
| 	// save index check, 0 will mean not found
 | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .placeholder | ||||
| 		name: 'reserved_0' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .void | ||||
| 		name: 'void' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .voidptr | ||||
| 		name: 'voidptr' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .byteptr | ||||
| 		name: 'byteptr' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .charptr | ||||
| 		name: 'charptr' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .i8 | ||||
| 		name: 'i8' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .i16 | ||||
| 		name: 'i16' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .int | ||||
| 		name: 'int' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .i64 | ||||
| 		name: 'i64' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .byte | ||||
| 		name: 'byte' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .u16 | ||||
| 		name: 'u16' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .u32 | ||||
| 		name: 'u32' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .u64 | ||||
| 		name: 'u64' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .f32 | ||||
| 		name: 'f32' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .f64 | ||||
| 		name: 'f64' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .char | ||||
| 		name: 'char' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .bool | ||||
| 		name: 'bool' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .none_ | ||||
| 		name: 'none' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .string | ||||
| 		name: 'string' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .array | ||||
| 		name: 'array' | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .map | ||||
| 		name: 'map' | ||||
| 	}) | ||||
| 	// TODO: remove. for v1 map compatibility
 | ||||
| 	map_string_string_idx := t.find_or_register_map(string_type, string_type) | ||||
| 	map_string_int_idx := t.find_or_register_map(string_type, int_type) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .alias | ||||
| 		name: 'map_string' | ||||
| 		parent_idx: map_string_string_idx | ||||
| 	}) | ||||
| 	t.register_type_symbol(TypeSymbol{ | ||||
| 		kind: .alias | ||||
| 		name: 'map_int' | ||||
| 		parent_idx: map_string_int_idx | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_int() bool { | ||||
| 	return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_float() bool { | ||||
| 	return t.kind in [.f32, .f64] | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_number() bool { | ||||
| 	return t.is_int() || t.is_float() | ||||
| } | ||||
| 
 | ||||
| pub fn (k Kind) str() string { | ||||
| 	k_str := match k { | ||||
| 		.placeholder{ | ||||
| 			'placeholder' | ||||
| 		} | ||||
| 		.void{ | ||||
| 			'void' | ||||
| 		} | ||||
| 		.voidptr{ | ||||
| 			'voidptr' | ||||
| 		} | ||||
| 		.charptr{ | ||||
| 			'charptr' | ||||
| 		} | ||||
| 		.byteptr{ | ||||
| 			'byteptr' | ||||
| 		} | ||||
| 		.struct_{ | ||||
| 			'struct' | ||||
| 		} | ||||
| 		.int{ | ||||
| 			'int' | ||||
| 		} | ||||
| 		.i8{ | ||||
| 			'i8' | ||||
| 		} | ||||
| 		.i16{ | ||||
| 			'i16' | ||||
| 		} | ||||
| 		.i64{ | ||||
| 			'i64' | ||||
| 		} | ||||
| 		.byte{ | ||||
| 			'byte' | ||||
| 		} | ||||
| 		.u16{ | ||||
| 			'u16' | ||||
| 		} | ||||
| 		.u32{ | ||||
| 			'u32' | ||||
| 		} | ||||
| 		.u64{ | ||||
| 			'u64' | ||||
| 		} | ||||
| 		.f32{ | ||||
| 			'f32' | ||||
| 		} | ||||
| 		.f64{ | ||||
| 			'f64' | ||||
| 		} | ||||
| 		.string{ | ||||
| 			'string' | ||||
| 		} | ||||
| 		.char{ | ||||
| 			'char' | ||||
| 		} | ||||
| 		.bool{ | ||||
| 			'bool' | ||||
| 		} | ||||
| 		.none_{ | ||||
| 			'none' | ||||
| 		} | ||||
| 		.array{ | ||||
| 			'array' | ||||
| 		} | ||||
| 		.array_fixed{ | ||||
| 			'array_fixed' | ||||
| 		} | ||||
| 		.map{ | ||||
| 			'map' | ||||
| 		} | ||||
| 		.multi_return{ | ||||
| 			'multi_return' | ||||
| 		} | ||||
| 		.sum_type{ | ||||
| 			'sum_type' | ||||
| 		} | ||||
| 		.alias{ | ||||
| 			'alias' | ||||
| 		} | ||||
| 		.enum_{ | ||||
| 			'enum' | ||||
| 		} | ||||
| 		else { | ||||
| 			'unknown'} | ||||
| 	} | ||||
| 	return k_str | ||||
| } | ||||
| 
 | ||||
| pub fn (kinds []Kind) str() string { | ||||
| 	mut kinds_str := '' | ||||
| 	for i, k in kinds { | ||||
| 		kinds_str += k.str() | ||||
| 		if i < kinds.len - 1 { | ||||
| 			kinds_str += '_' | ||||
| 		} | ||||
| 	} | ||||
| 	return kinds_str | ||||
| } | ||||
| 
 | ||||
| pub struct Struct { | ||||
| pub mut: | ||||
| 	fields []Field | ||||
| } | ||||
| 
 | ||||
| pub struct Enum { | ||||
| pub mut: | ||||
| 	vals []string | ||||
| } | ||||
| 
 | ||||
| pub struct Alias { | ||||
| pub: | ||||
| 	foo string | ||||
| } | ||||
| 
 | ||||
| pub struct Field { | ||||
| pub: | ||||
| 	name string | ||||
| mut: | ||||
| 	typ  Type | ||||
| } | ||||
| 
 | ||||
| pub struct Array { | ||||
| pub: | ||||
| 	nr_dims   int | ||||
| mut: | ||||
| 	elem_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct ArrayFixed { | ||||
| pub: | ||||
| 	nr_dims   int | ||||
| 	size      int | ||||
| mut: | ||||
| 	elem_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct Map { | ||||
| pub mut: | ||||
| 	key_type   Type | ||||
| 	value_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct SumType { | ||||
| pub: | ||||
| 	variants []Type | ||||
| } | ||||
| 
 | ||||
| pub fn (table &Table) type_to_str(t Type) string { | ||||
| 	sym := table.get_type_symbol(t) | ||||
| 	if sym.kind == .multi_return { | ||||
| 		mut res := '(' | ||||
| 		mr_info := sym.info as MultiReturn | ||||
| 		for i, typ in mr_info.types { | ||||
| 			res += table.type_to_str(typ) | ||||
| 			if i < mr_info.types.len - 1 { | ||||
| 				res += ', ' | ||||
| 			} | ||||
| 		} | ||||
| 		res += ')' | ||||
| 		return res | ||||
| 	} | ||||
| 	mut res := sym.name | ||||
| 	if sym.kind == .array { | ||||
| 		res = res.replace('array_', '[]') | ||||
| 	} | ||||
| 	else if sym.kind == .map { | ||||
| 		res = res.replace('map_string_', 'map[string]') | ||||
| 	} | ||||
| 	// mod.submod.submod2.Type => submod2.Type
 | ||||
| 	if res.contains('.') { | ||||
| 		vals := res.split('.') | ||||
| 		if vals.len > 2 { | ||||
| 			res = vals[vals.len - 2] + '.' + vals[vals.len - 1] | ||||
| 		} | ||||
| 	} | ||||
| 	if type_is_optional(t) { | ||||
| 		res = '?' + res | ||||
| 	} | ||||
| 	nr_muls := type_nr_muls(t) | ||||
| 	if nr_muls > 0 { | ||||
| 		res = strings.repeat(`&`, nr_muls) + res | ||||
| 	} | ||||
| 	/* | ||||
| 	if res.starts_with(cur_mod +'.') { | ||||
| 	res = res[cur_mod.len+1.. ] | ||||
| 	} | ||||
| 	*/ | ||||
| 
 | ||||
| 	return res | ||||
| } | ||||
|  | @ -3,6 +3,10 @@ | |||
| // that can be found in the LICENSE file.
 | ||||
| module table | ||||
| 
 | ||||
| import ( | ||||
| 	strings | ||||
| ) | ||||
| 
 | ||||
| pub struct Table { | ||||
| 	// struct_fields map[string][]string
 | ||||
| pub mut: | ||||
|  | @ -56,7 +60,7 @@ pub fn (t mut Table) register_global(name string, typ Type) { | |||
| 		// mod: p.mod
 | ||||
| 		// is_mut: true
 | ||||
| 		// idx: -1
 | ||||
| 		 | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,153 +0,0 @@ | |||
| module table | ||||
| 
 | ||||
| pub type Type int | ||||
| 
 | ||||
| pub enum TypeExtra { | ||||
| 	unset | ||||
| 	optional | ||||
| 	variadic | ||||
| } | ||||
| 
 | ||||
| pub fn (types []Type) contains(typ Type) bool { | ||||
| 	for t in types { | ||||
| 		if int(typ) == int(t) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // return underlying TypeSymbol idx
 | ||||
| [inline] | ||||
| pub fn type_idx(t Type) int { | ||||
| 	return u16(t) & 0xffff | ||||
| } | ||||
| 
 | ||||
| // return nr_muls
 | ||||
| [inline] | ||||
| pub fn type_nr_muls(t Type) int { | ||||
| 	return (int(t)>>16) & 0xff | ||||
| } | ||||
| 
 | ||||
| // return true if pointer (nr_muls>0)
 | ||||
| [inline] | ||||
| pub fn type_is_ptr(t Type) bool { | ||||
| 	return type_nr_muls(t) > 0 // || t == voidptr_type_idx
 | ||||
| } | ||||
| // set nr_muls on Type and return it
 | ||||
| [inline] | ||||
| pub fn type_set_nr_muls(t Type, nr_muls int) Type { | ||||
| 	if nr_muls < 0 || nr_muls > 255 { | ||||
| 		panic('typ_set_nr_muls: nr_muls must be between 0 & 255') | ||||
| 	} | ||||
| 	return (int(type_extra(t))<<24) | (nr_muls<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| // increments nr_nuls on Type and return it
 | ||||
| [inline] | ||||
| pub fn type_to_ptr(t Type) Type { | ||||
| 	nr_muls := type_nr_muls(t) | ||||
| 	if nr_muls == 255 { | ||||
| 		panic('type_to_pre: nr_muls is already at max of 255') | ||||
| 	} | ||||
| 	return (int(type_extra(t))<<24) | ((nr_muls + 1)<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| // decrement nr_muls on Type and return it
 | ||||
| [inline] | ||||
| pub fn type_deref(t Type) Type { | ||||
| 	nr_muls := type_nr_muls(t) | ||||
| 	if nr_muls == 0 { | ||||
| 		panic('deref: type `$t` is not a pointer') | ||||
| 	} | ||||
| 	return (int(type_extra(t))<<24) | ((nr_muls - 1)<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| // return extra info
 | ||||
| [inline] | ||||
| pub fn type_extra(t Type) TypeExtra { | ||||
| 	return (int(t)>>24) & 0xff | ||||
| } | ||||
| 
 | ||||
| // set extra info
 | ||||
| [inline] | ||||
| pub fn type_set_extra(t Type, extra TypeExtra) Type { | ||||
| 	return (int(extra)<<24) | (type_nr_muls(t)<<16) | u16(type_idx(t)) | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_is_optional(t Type) bool { | ||||
| 	return type_extra(t) == .optional | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_to_optional(t Type) Type { | ||||
| 	return type_set_extra(t, .optional) | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_is_variadic(t Type) bool { | ||||
| 	return type_extra(t) == .variadic | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn type_to_variadic(t Type) Type { | ||||
| 	return type_set_extra(t, .variadic) | ||||
| } | ||||
| 
 | ||||
| // new type with idx of TypeSymbol, not pointer (nr_muls=0)
 | ||||
| [inline] | ||||
| pub fn new_type(idx int) Type { | ||||
| 	if idx < 1 || idx > 65536 { | ||||
| 		panic('new_type_id: idx must be between 1 & 65536') | ||||
| 	} | ||||
| 	return idx | ||||
| } | ||||
| 
 | ||||
| // return Type idx of TypeSymbol & specify if ptr (nr_muls)
 | ||||
| [inline] | ||||
| pub fn new_type_ptr(idx int, nr_muls int) Type { | ||||
| 	if idx < 1 || idx > 65536 { | ||||
| 		panic('typ_ptr: idx must be between 1 & 65536') | ||||
| 	} | ||||
| 	if nr_muls < 0 || nr_muls > 255 { | ||||
| 		panic('typ_ptr: nr_muls must be between 0 & 255') | ||||
| 	} | ||||
| 	return (nr_muls<<16) | u16(idx) | ||||
| } | ||||
| 
 | ||||
| pub const ( | ||||
| 	number_idxs = [int_type_idx, byte_type_idx, u16_type_idx, i16_type_idx, i64_type_idx, u32_type_idx, u64_type_idx] | ||||
| ) | ||||
| /* | ||||
| pub fn is_number(typ Type) bool { | ||||
| 	typ_sym := c.table.get_type_symbol(typ) | ||||
| 	return typ_sym.is_int() | ||||
| 	//idx := type_idx(typ)
 | ||||
| 	//return idx in [int_type_idx, byte_type_idx, u64_type_idx]
 | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| pub const ( | ||||
| 	void_type = new_type(void_type_idx) | ||||
| 	voidptr_type = new_type(voidptr_type_idx) | ||||
| 	byteptr_type = new_type(byteptr_type_idx) | ||||
| 	charptr_type = new_type(charptr_type_idx) | ||||
| 	i8_type = new_type(i8_type_idx) | ||||
| 	int_type = new_type(int_type_idx) | ||||
| 	i16_type = new_type(i16_type_idx) | ||||
| 	i64_type = new_type(i64_type_idx) | ||||
| 	byte_type = new_type(byte_type_idx) | ||||
| 	u16_type = new_type(u16_type_idx) | ||||
| 	u32_type = new_type(u32_type_idx) | ||||
| 	u64_type = new_type(u64_type_idx) | ||||
| 	f32_type = new_type(f32_type_idx) | ||||
| 	f64_type = new_type(f64_type_idx) | ||||
| 	char_type = new_type(char_type_idx) | ||||
| 	bool_type = new_type(bool_type_idx) | ||||
| 	none_type = new_type(none_type_idx) | ||||
| 	string_type = new_type(string_type_idx) | ||||
| 	array_type = new_type(array_type_idx) | ||||
| 	map_type = new_type(map_type_idx) | ||||
| ) | ||||
|  | @ -0,0 +1,48 @@ | |||
| import os | ||||
| import term | ||||
| 
 | ||||
| fn test_all() { | ||||
| 	files := os.ls('.') or { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	for file in files { | ||||
| 		if !file.ends_with('.vv') { | ||||
| 			continue | ||||
| 		} | ||||
| 		print(file + ' ') | ||||
| 		program := file.replace('.vv', '.v') | ||||
| 		os.cp(file, program) or { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		os.rm('exe') | ||||
| 		x := os.exec('v -o exe -cflags "-w" -cg -backend experimental $program') or { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		println(x.output.limit(30)) | ||||
| 		os.rm(program) | ||||
| 		res := os.exec('./exe') or { | ||||
| 			println('nope') | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		// println('============')
 | ||||
| 		// println(res.output)
 | ||||
| 		// println('============')
 | ||||
| 		mut expected := os.read_file(program.replace('.v', '') + '.out') or { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		expected = expected.trim_space() | ||||
| 		found := res.output.trim_space() | ||||
| 		if expected != found { | ||||
| 			println(term.red('FAIL')) | ||||
| 			println('============') | ||||
| 			println('expected:') | ||||
| 			println(expected) | ||||
| 			println('\nfound:') | ||||
| 			println(found) | ||||
| 			println('============') | ||||
| 		} | ||||
| 		else { | ||||
| 			println(term.green('OK')) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1 @@ | |||
| hello world | ||||
|  | @ -0,0 +1,3 @@ | |||
| fn main() { | ||||
| 	println('hello world') | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| Hello, game developers! | ||||
| Hello, web developers! | ||||
| Hello, tools developers! | ||||
| Hello, science developers! | ||||
| Hello, systems developers! | ||||
| Hello, embedded developers! | ||||
|  | @ -0,0 +1,7 @@ | |||
| fn main() { | ||||
| 	areas := ['game', 'web', 'tools', 'science', 'systems', 'embedded'] | ||||
| 	for i :=0;i<areas.len; i++{ | ||||
| 		area:=areas[i] | ||||
| 		println('Hello, $area developers!') | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1 @@ | |||
| compiler_test.v | ||||
|  | @ -0,0 +1,10 @@ | |||
| import os | ||||
| 
 | ||||
| fn main() { | ||||
| 	files := os.ls('.') or { panic(err) } | ||||
| 	for file in files { | ||||
| 		if file.ends_with('_test.v') { | ||||
| 			println(file) | ||||
| 		} | ||||
| }	 | ||||
| } | ||||
|  | @ -427,46 +427,6 @@ pub fn (tok Token) is_unary() bool { | |||
| 	.plus, .minus, .not, .bit_not, .mul, .amp] | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| // NOTE: do we need this for all tokens (is_left_assoc / is_right_assoc),
 | ||||
| // or only ones with the same precedence?
 | ||||
| // is_left_assoc returns true if the token is left associative
 | ||||
| pub fn (tok Token) is_left_assoc() bool { | ||||
| 	return tok.kind in [ | ||||
| 	// `.`
 | ||||
| 	.dot, | ||||
| 	// `+` | `-`
 | ||||
| 	.plus, .minus, // additive
 | ||||
| 	// .number,
 | ||||
| 	// `++` | `--`
 | ||||
| 	.inc, .dec, | ||||
| 	// `*` | `/` | `%`
 | ||||
| 	.mul, .div, .mod, | ||||
| 	// `^` | `||` | `&`
 | ||||
| 	.xor, .logical_or, .and, | ||||
| 	// `==` | `!=`
 | ||||
| 	.eq, .ne, | ||||
| 	// `<` | `<=` | `>` | `>=`
 | ||||
| 	.lt, .le, .gt, .ge, .ne, .eq, | ||||
| 	// `,`
 | ||||
| 	.comma] | ||||
| } | ||||
| 
 | ||||
| // is_right_assoc returns true if the token is right associative
 | ||||
| pub fn (tok Token) is_right_assoc() bool { | ||||
| 	return tok.kind in [ | ||||
| 	// `+` | `-` | `!`
 | ||||
| 	.plus, .minus, .not, // unary
 | ||||
| 	// `=` | `+=` | `-=` | `*=` | `/=`
 | ||||
| 	.assign, .plus_assign, .minus_assign, .mult_assign, .div_assign, | ||||
| 	// `%=` | `>>=` | `<<=`
 | ||||
| 	.mod_assign, .right_shift_assign, .left_shift_assign, | ||||
| 	// `&=` | `^=` | `|=`
 | ||||
| 	.and_assign, .xor_assign, .or_assign] | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| pub fn (tok Kind) is_relational() bool { | ||||
| 	return tok in [ | ||||
| 	// `<` | `<=` | `>` | `>=`
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue