parser: `[]int{cap:cap, len:len}` syntax; minor fixes
							parent
							
								
									893d14ef8f
								
							
						
					
					
						commit
						ec10831318
					
				|  | @ -691,3 +691,8 @@ fn test_hex(){ | ||||||
| 	st1 := [byte(0x41)].repeat(100) | 	st1 := [byte(0x41)].repeat(100) | ||||||
| 	assert st1.hex() == "41".repeat(100) | 	assert st1.hex() == "41".repeat(100) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn test_array_with_cap() { | ||||||
|  | 	a := []int{cap:10, len:1 } | ||||||
|  | 	//assert a.len == 1
 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -444,6 +444,9 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type { | ||||||
| 			if typ_sym.kind == .void && arg_typ_sym.kind == .string { | 			if typ_sym.kind == .void && arg_typ_sym.kind == .string { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|  | 			if f.is_generic { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
| 			if typ_sym.kind == .array_fixed { | 			if typ_sym.kind == .array_fixed { | ||||||
| 			} | 			} | ||||||
| 			// println('fixed')
 | 			// println('fixed')
 | ||||||
|  | @ -1333,7 +1336,6 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { | ||||||
| 		c.error('match 0 cond type', node.pos) | 		c.error('match 0 cond type', node.pos) | ||||||
| 	} | 	} | ||||||
| 	type_sym := c.table.get_type_symbol(cond_type) | 	type_sym := c.table.get_type_symbol(cond_type) | ||||||
| 
 |  | ||||||
| 	// all_possible_left_subtypes is a histogram of
 | 	// all_possible_left_subtypes is a histogram of
 | ||||||
| 	// type => how many times it was used in the match
 | 	// type => how many times it was used in the match
 | ||||||
| 	mut all_possible_left_subtypes := map[string]int | 	mut all_possible_left_subtypes := map[string]int | ||||||
|  | @ -1343,7 +1345,7 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { | ||||||
| 	match type_sym.info { | 	match type_sym.info { | ||||||
| 		table.SumType { | 		table.SumType { | ||||||
| 			for v in it.variants { | 			for v in it.variants { | ||||||
| 				all_possible_left_subtypes[ int(v).str() ] = 0 | 				all_possible_left_subtypes[int(v).str()] = 0 | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		table.Enum { | 		table.Enum { | ||||||
|  | @ -1362,12 +1364,14 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { | ||||||
| 					ast.Type { | 					ast.Type { | ||||||
| 						tidx := table.type_idx(it.typ) | 						tidx := table.type_idx(it.typ) | ||||||
| 						stidx := tidx.str() | 						stidx := tidx.str() | ||||||
| 						all_possible_left_subtypes[ stidx ] = all_possible_left_subtypes[ stidx ] + 1 | 						all_possible_left_subtypes[stidx] = all_possible_left_subtypes[stidx] + | ||||||
|  | 							1 | ||||||
| 					} | 					} | ||||||
| 					ast.EnumVal { | 					ast.EnumVal { | ||||||
| 						all_possible_left_enum_vals[ it.val ] = all_possible_left_enum_vals[ it.val ] + 1 | 						all_possible_left_enum_vals[it.val] = all_possible_left_enum_vals[it.val] + | ||||||
|  | 							1 | ||||||
| 					} | 					} | ||||||
| 					else{} | 					else {} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1376,20 +1380,22 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { | ||||||
| 		unhandled := []string | 		unhandled := []string | ||||||
| 		match type_sym.info { | 		match type_sym.info { | ||||||
| 			table.SumType { | 			table.SumType { | ||||||
| 				for k,v in all_possible_left_subtypes { | 				for k, v in all_possible_left_subtypes { | ||||||
| 					if v == 0 { | 					if v == 0 { | ||||||
| 						err = true | 						err = true | ||||||
| 						unhandled << '`' + c.table.type_to_str( table.new_type( k.int() ) ) + '`' | 						unhandled << '`' + c.table.type_to_str(table.new_type(k.int())) + '`' | ||||||
| 					} | 					} | ||||||
| 					if v > 1 { | 					if v > 1 { | ||||||
| 						err = true | 						err = true | ||||||
| 						multiple_type_name := '`' + c.table.type_to_str( table.new_type( k.int() ) ) + '`' | 						multiple_type_name := '`' + c.table.type_to_str(table.new_type(k.int())) + | ||||||
| 						c.error('a match case for $multiple_type_name is handled more than once', node.pos) | 							'`' | ||||||
|  | 						c.error('a match case for $multiple_type_name is handled more than once', | ||||||
|  | 							node.pos) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			table.Enum { | 			table.Enum { | ||||||
| 				for k,v in all_possible_left_enum_vals { | 				for k, v in all_possible_left_enum_vals { | ||||||
| 					if v == 0 { | 					if v == 0 { | ||||||
| 						err = true | 						err = true | ||||||
| 						unhandled << '`.$k`' | 						unhandled << '`.$k`' | ||||||
|  | @ -1397,11 +1403,14 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { | ||||||
| 					if v > 1 { | 					if v > 1 { | ||||||
| 						err = true | 						err = true | ||||||
| 						multiple_enum_val := '`.$k`' | 						multiple_enum_val := '`.$k`' | ||||||
| 						c.error('a match case for $multiple_enum_val is handled more than once', node.pos) | 						c.error('a match case for $multiple_enum_val is handled more than once', | ||||||
|  | 							node.pos) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else { err = true } | 			else { | ||||||
|  | 				err = true | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		if err { | 		if err { | ||||||
| 			if unhandled.len > 0 { | 			if unhandled.len > 0 { | ||||||
|  | @ -1410,7 +1419,6 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { | ||||||
| 			c.error(err_details, node.pos) | 			c.error(err_details, node.pos) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	c.expected_type = cond_type | 	c.expected_type = cond_type | ||||||
| 	mut ret_type := table.void_type | 	mut ret_type := table.void_type | ||||||
| 	for branch in node.branches { | 	for branch in node.branches { | ||||||
|  |  | ||||||
|  | @ -553,6 +553,15 @@ fn (f mut Fmt) expr(node ast.Expr) { | ||||||
| 			f.write(it.val) | 			f.write(it.val) | ||||||
| 		} | 		} | ||||||
| 		ast.MapInit { | 		ast.MapInit { | ||||||
|  | 			if it.keys.len == 0 { | ||||||
|  | 				if it.value_type == 0 { | ||||||
|  | 					f.write('map[string]int') // TODO
 | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				f.write('map[string]') | ||||||
|  | 				f.write(f.type_to_str(it.value_type)) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 			f.writeln('{') | 			f.writeln('{') | ||||||
| 			f.indent++ | 			f.indent++ | ||||||
| 			for i, key in it.keys { | 			for i, key in it.keys { | ||||||
|  |  | ||||||
|  | @ -212,9 +212,13 @@ pub fn (g mut Gen) typ(t table.Type) string { | ||||||
| 	if table.type_is(t, .optional) { | 	if table.type_is(t, .optional) { | ||||||
| 		// Register an optional
 | 		// Register an optional
 | ||||||
| 		styp = 'Option_' + styp | 		styp = 'Option_' + styp | ||||||
|  | 		if table.type_is_ptr(t) { | ||||||
|  | 			styp = styp.replace('*', '_ptr') | ||||||
|  | 		} | ||||||
| 		if !(styp in g.optionals) { | 		if !(styp in g.optionals) { | ||||||
| 			// println(styp)
 | 			// println(styp)
 | ||||||
| 			g.typedefs2.writeln('typedef Option $styp;') | 			x := styp			// .replace('*', '_ptr')			// handle option ptrs
 | ||||||
|  | 			g.typedefs2.writeln('typedef Option $x;') | ||||||
| 			g.optionals << styp | 			g.optionals << styp | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1744,7 +1748,11 @@ fn (g mut Gen) return_statement(node ast.Return) { | ||||||
| 		mut styp := g.typ(g.fn_decl.return_type) | 		mut styp := g.typ(g.fn_decl.return_type) | ||||||
| 		if fn_return_is_optional {			// && !table.type_is(node.types[0], .optional) && node.types[0] !=
 | 		if fn_return_is_optional {			// && !table.type_is(node.types[0], .optional) && node.types[0] !=
 | ||||||
| 			styp = styp[7..]			// remove 'Option_'
 | 			styp = styp[7..]			// remove 'Option_'
 | ||||||
| 			g.write('opt_ok(& ($styp []) { ') | 			mut x := styp | ||||||
|  | 			if x.ends_with('_ptr') { | ||||||
|  | 				x = x.replace('_ptr', '*') | ||||||
|  | 			} | ||||||
|  | 			g.write('opt_ok(&($x/*X*/[]) { ') | ||||||
| 		} | 		} | ||||||
| 		g.write('($styp){') | 		g.write('($styp){') | ||||||
| 		for i, expr in node.exprs { | 		for i, expr in node.exprs { | ||||||
|  | @ -1783,9 +1791,13 @@ fn (g mut Gen) return_statement(node ast.Return) { | ||||||
| 			} | 			} | ||||||
| 			if !is_none && !is_error { | 			if !is_none && !is_error { | ||||||
| 				styp := g.typ(g.fn_decl.return_type)[7..]				// remove 'Option_'
 | 				styp := g.typ(g.fn_decl.return_type)[7..]				// remove 'Option_'
 | ||||||
| 				g.write('/*:)$return_sym.name*/opt_ok(&($styp []) { ') | 				mut x := styp | ||||||
|  | 				if x.ends_with('_ptr') { | ||||||
|  | 					x = x.replace('_ptr', '*') | ||||||
|  | 				} | ||||||
|  | 				g.write('/*:)$return_sym.name*/opt_ok(&($x[]) { ') | ||||||
| 				g.expr(node.exprs[0]) | 				g.expr(node.exprs[0]) | ||||||
| 				g.writeln(' }, sizeof($styp));') | 				g.writeln(' }, sizeof($x));') | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			// g.write('/*OPTIONAL*/')
 | 			// g.write('/*OPTIONAL*/')
 | ||||||
|  |  | ||||||
|  | @ -141,7 +141,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl { | ||||||
| 		p.next() | 		p.next() | ||||||
| 	} | 	} | ||||||
| 	// <T>
 | 	// <T>
 | ||||||
| 	if p.tok.kind == .lt { | 	is_generic := p.tok.kind == .lt | ||||||
|  | 	if is_generic { | ||||||
| 		p.next() | 		p.next() | ||||||
| 		p.next() | 		p.next() | ||||||
| 		p.check(.gt) | 		p.check(.gt) | ||||||
|  | @ -169,6 +170,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { | ||||||
| 			args: args | 			args: args | ||||||
| 			return_type: return_type | 			return_type: return_type | ||||||
| 			is_variadic: is_variadic | 			is_variadic: is_variadic | ||||||
|  | 			is_generic: is_generic | ||||||
| 		}) | 		}) | ||||||
| 	} else { | 	} else { | ||||||
| 		if is_c { | 		if is_c { | ||||||
|  | @ -185,6 +187,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { | ||||||
| 			return_type: return_type | 			return_type: return_type | ||||||
| 			is_variadic: is_variadic | 			is_variadic: is_variadic | ||||||
| 			is_c: is_c | 			is_c: is_c | ||||||
|  | 			is_generic: is_generic | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 	// Body
 | 	// Body
 | ||||||
|  |  | ||||||
|  | @ -1351,15 +1351,12 @@ fn (p mut Parser) array_init() ast.ArrayInit { | ||||||
| 			// p.check_comment()
 | 			// p.check_comment()
 | ||||||
| 		} | 		} | ||||||
| 		line_nr := p.tok.line_nr | 		line_nr := p.tok.line_nr | ||||||
| 
 |  | ||||||
| 		$if tinyc { | 		$if tinyc { | ||||||
| 			// NB: do not remove the next line without testing
 | 			// NB: do not remove the next line without testing
 | ||||||
| 			// v selfcompilation with tcc first
 | 			// v selfcompilation with tcc first
 | ||||||
| 			tcc_stack_bug := 12345 | 			tcc_stack_bug := 12345 | ||||||
| 		} | 		} | ||||||
| 	    |  | ||||||
| 		last_pos = p.tok.position() | 		last_pos = p.tok.position() | ||||||
| 
 |  | ||||||
| 		p.check(.rsbr) | 		p.check(.rsbr) | ||||||
| 		// [100]byte
 | 		// [100]byte
 | ||||||
| 		if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr { | 		if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr { | ||||||
|  | @ -1376,6 +1373,22 @@ fn (p mut Parser) array_init() ast.ArrayInit { | ||||||
| 		last_pos = p.tok.position() | 		last_pos = p.tok.position() | ||||||
| 		p.next() | 		p.next() | ||||||
| 	} | 	} | ||||||
|  | 	if p.tok.kind == .lcbr && exprs.len == 0 { | ||||||
|  | 		// `[]int{ len: 10, cap: 100}` syntax
 | ||||||
|  | 		p.next() | ||||||
|  | 		for p.tok.kind != .rcbr { | ||||||
|  | 			key := p.check_name() | ||||||
|  | 			p.check(.colon) | ||||||
|  | 			if !(key in ['len', 'cap', 'init']) { | ||||||
|  | 				p.error('wrong field `$key`, expecting `len`, `cap`, or `init`') | ||||||
|  | 			} | ||||||
|  | 			p.expr(0) | ||||||
|  | 			if p.tok.kind != .rcbr { | ||||||
|  | 				p.check(.comma) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		p.check(.rcbr) | ||||||
|  | 	} | ||||||
| 	pos := token.Position{ | 	pos := token.Position{ | ||||||
| 		line_nr: first_pos.line_nr | 		line_nr: first_pos.line_nr | ||||||
| 		pos: first_pos.pos | 		pos: first_pos.pos | ||||||
|  | @ -1594,7 +1607,9 @@ fn (p mut Parser) struct_decl() ast.StructDecl { | ||||||
| 				// p.expr(0)
 | 				// p.expr(0)
 | ||||||
| 				default_expr = p.expr(0) | 				default_expr = p.expr(0) | ||||||
| 				match default_expr { | 				match default_expr { | ||||||
| 					ast.EnumVal { it.typ = typ } | 					ast.EnumVal { | ||||||
|  | 						it.typ = typ | ||||||
|  | 					} | ||||||
| 					// TODO: implement all types??
 | 					// TODO: implement all types??
 | ||||||
| 					else {} | 					else {} | ||||||
| 				} | 				} | ||||||
|  | @ -1865,8 +1880,8 @@ fn (p mut Parser) match_expr() ast.MatchExpr { | ||||||
| 		if p.tok.kind == .key_else { | 		if p.tok.kind == .key_else { | ||||||
| 			is_else = true | 			is_else = true | ||||||
| 			p.next() | 			p.next() | ||||||
| 		} else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || | 		} else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || (p.tok.lit[0].is_capital() && | ||||||
| 				(p.tok.lit[0].is_capital() && !p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) { | 			!p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) { | ||||||
| 			// Sum type match
 | 			// Sum type match
 | ||||||
| 			// if sym.kind == .sum_type {
 | 			// if sym.kind == .sum_type {
 | ||||||
| 			// p.warn('is sum')
 | 			// p.warn('is sum')
 | ||||||
|  | @ -1993,7 +2008,7 @@ fn (p mut Parser) type_decl() ast.TypeDecl { | ||||||
| 	name := p.check_name() | 	name := p.check_name() | ||||||
| 	mut sum_variants := []table.Type | 	mut sum_variants := []table.Type | ||||||
| 	if p.tok.kind == .assign { | 	if p.tok.kind == .assign { | ||||||
| 		p.next()  // TODO require `=`
 | 		p.next()		// TODO require `=`
 | ||||||
| 	} | 	} | ||||||
| 	if p.tok.kind == .key_fn { | 	if p.tok.kind == .key_fn { | ||||||
| 		// function type: `type mycallback fn(string, int)`
 | 		// function type: `type mycallback fn(string, int)`
 | ||||||
|  | @ -2005,7 +2020,7 @@ fn (p mut Parser) type_decl() ast.TypeDecl { | ||||||
| 			typ: fn_type | 			typ: fn_type | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	first_type := p.parse_type() // need to parse the first type before we can check if it's `type A = X | Y`
 | 	first_type := p.parse_type()	// need to parse the first type before we can check if it's `type A = X | Y`
 | ||||||
| 	if p.tok.kind == .pipe { | 	if p.tok.kind == .pipe { | ||||||
| 		p.check(.pipe) | 		p.check(.pipe) | ||||||
| 		sum_variants << first_type | 		sum_variants << first_type | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ pub: | ||||||
| 	return_type Type | 	return_type Type | ||||||
| 	is_variadic bool | 	is_variadic bool | ||||||
| 	is_c        bool | 	is_c        bool | ||||||
|  | 	is_generic  bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct Arg { | pub struct Arg { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue