table: move Type functions to methods
							parent
							
								
									6248899d25
								
							
						
					
					
						commit
						fbcdffbbc8
					
				| 
						 | 
					@ -24,7 +24,7 @@ pub fn (node &FnDecl) str(t &table.Table) string {
 | 
				
			||||||
		sym := t.get_type_symbol(node.receiver.typ)
 | 
							sym := t.get_type_symbol(node.receiver.typ)
 | 
				
			||||||
		name := sym.name.after('.')
 | 
							name := sym.name.after('.')
 | 
				
			||||||
		mut m := if node.rec_mut { 'mut ' } else { '' }
 | 
							mut m := if node.rec_mut { 'mut ' } else { '' }
 | 
				
			||||||
		if !node.rec_mut && table.type_is_ptr(node.receiver.typ) {
 | 
							if !node.rec_mut && node.receiver.typ.is_ptr() {
 | 
				
			||||||
			m = '&'
 | 
								m = '&'
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		receiver = '($node.receiver.name $m$name) '
 | 
							receiver = '($node.receiver.name $m$name) '
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,7 +258,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
 | 
				
			||||||
				if field.name in inited_fields {
 | 
									if field.name in inited_fields {
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if table.type_is_ptr(field.typ) {
 | 
									if field.typ.is_ptr() {
 | 
				
			||||||
					c.warn('reference field `${type_sym.name}.${field.name}` must be initialized',
 | 
										c.warn('reference field `${type_sym.name}.${field.name}` must be initialized',
 | 
				
			||||||
						struct_init.pos)
 | 
											struct_init.pos)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -478,7 +478,7 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
 | 
				
			||||||
		call_expr.return_type = left_type
 | 
							call_expr.return_type = left_type
 | 
				
			||||||
		if method_name == 'clone' {
 | 
							if method_name == 'clone' {
 | 
				
			||||||
			// in ['clone', 'str'] {
 | 
								// in ['clone', 'str'] {
 | 
				
			||||||
			call_expr.receiver_type = table.type_to_ptr(left_type)
 | 
								call_expr.receiver_type = left_type.to_ptr()
 | 
				
			||||||
			// call_expr.return_type = call_expr.receiver_type
 | 
								// call_expr.return_type = call_expr.receiver_type
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			call_expr.receiver_type = left_type
 | 
								call_expr.receiver_type = left_type
 | 
				
			||||||
| 
						 | 
					@ -520,7 +520,7 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			arg_typ := c.expr(arg.expr)
 | 
								arg_typ := c.expr(arg.expr)
 | 
				
			||||||
			call_expr.args[i].typ = arg_typ
 | 
								call_expr.args[i].typ = arg_typ
 | 
				
			||||||
			if method.is_variadic && table.type_is(arg_typ, .variadic) && call_expr.args.len-1 > i  {
 | 
								if method.is_variadic && arg_typ.flag_is(.variadic) && call_expr.args.len-1 > i  {
 | 
				
			||||||
				c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
 | 
									c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -646,7 +646,7 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
 | 
				
			||||||
		call_expr.args[i].typ = typ
 | 
							call_expr.args[i].typ = typ
 | 
				
			||||||
		typ_sym := c.table.get_type_symbol(typ)
 | 
							typ_sym := c.table.get_type_symbol(typ)
 | 
				
			||||||
		arg_typ_sym := c.table.get_type_symbol(arg.typ)
 | 
							arg_typ_sym := c.table.get_type_symbol(arg.typ)
 | 
				
			||||||
		if f.is_variadic && table.type_is(typ, .variadic) && call_expr.args.len-1 > i {
 | 
							if f.is_variadic && typ.flag_is(.variadic) && call_expr.args.len-1 > i {
 | 
				
			||||||
			c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
 | 
								c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !c.table.check(typ, arg.typ) {
 | 
							if !c.table.check(typ, arg.typ) {
 | 
				
			||||||
| 
						 | 
					@ -673,7 +673,7 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
 | 
				
			||||||
pub fn (c mut Checker) check_expr_opt_call(x ast.Expr, xtype table.Type, is_return_used bool) {
 | 
					pub fn (c mut Checker) check_expr_opt_call(x ast.Expr, xtype table.Type, is_return_used bool) {
 | 
				
			||||||
	match x {
 | 
						match x {
 | 
				
			||||||
		ast.CallExpr {
 | 
							ast.CallExpr {
 | 
				
			||||||
			if table.type_is(it.return_type, .optional) {
 | 
								if it.return_type.flag_is(.optional) {
 | 
				
			||||||
				c.check_or_block(it, xtype, is_return_used)
 | 
									c.check_or_block(it, xtype, is_return_used)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -771,7 +771,7 @@ pub fn (c mut Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.T
 | 
				
			||||||
	typ_sym := c.table.get_type_symbol(typ)
 | 
						typ_sym := c.table.get_type_symbol(typ)
 | 
				
			||||||
	field_name := selector_expr.field
 | 
						field_name := selector_expr.field
 | 
				
			||||||
	// variadic
 | 
						// variadic
 | 
				
			||||||
	if table.type_is(typ, .variadic) {
 | 
						if typ.flag_is(.variadic) {
 | 
				
			||||||
		if field_name == 'len' {
 | 
							if field_name == 'len' {
 | 
				
			||||||
			return table.int_type
 | 
								return table.int_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -803,7 +803,7 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	expected_type := c.fn_return_type
 | 
						expected_type := c.fn_return_type
 | 
				
			||||||
	expected_type_sym := c.table.get_type_symbol(expected_type)
 | 
						expected_type_sym := c.table.get_type_symbol(expected_type)
 | 
				
			||||||
	exp_is_optional := table.type_is(expected_type, .optional)
 | 
						exp_is_optional := expected_type.flag_is(.optional)
 | 
				
			||||||
	mut expected_types := [expected_type]
 | 
						mut expected_types := [expected_type]
 | 
				
			||||||
	if expected_type_sym.kind == .multi_return {
 | 
						if expected_type_sym.kind == .multi_return {
 | 
				
			||||||
		mr_info := expected_type_sym.info as table.MultiReturn
 | 
							mr_info := expected_type_sym.info as table.MultiReturn
 | 
				
			||||||
| 
						 | 
					@ -816,7 +816,7 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return_stmt.types = got_types
 | 
						return_stmt.types = got_types
 | 
				
			||||||
	// allow `none` & `error (Option)` return types for function that returns optional
 | 
						// allow `none` & `error (Option)` return types for function that returns optional
 | 
				
			||||||
	if exp_is_optional && table.type_idx(got_types[0]) in [table.none_type_idx, c.table.type_idxs['Option']] {
 | 
						if exp_is_optional && got_types[0].idx() in [table.none_type_idx, c.table.type_idxs['Option']] {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if expected_types.len > 0 && expected_types.len != got_types.len {
 | 
						if expected_types.len > 0 && expected_types.len != got_types.len {
 | 
				
			||||||
| 
						 | 
					@ -1144,7 +1144,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
 | 
				
			||||||
		ast.ForStmt {
 | 
							ast.ForStmt {
 | 
				
			||||||
			c.in_for_count++
 | 
								c.in_for_count++
 | 
				
			||||||
			typ := c.expr(it.cond)
 | 
								typ := c.expr(it.cond)
 | 
				
			||||||
			if !it.is_inf && table.type_idx(typ) != table.bool_type_idx {
 | 
								if !it.is_inf && typ.idx() != table.bool_type_idx {
 | 
				
			||||||
				c.error('non-bool used as for condition', it.pos)
 | 
									c.error('non-bool used as for condition', it.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// TODO: update loop var type
 | 
								// TODO: update loop var type
 | 
				
			||||||
| 
						 | 
					@ -1164,9 +1164,9 @@ fn (c mut Checker) stmt(node ast.Stmt) {
 | 
				
			||||||
		ast.ForInStmt {
 | 
							ast.ForInStmt {
 | 
				
			||||||
			c.in_for_count++
 | 
								c.in_for_count++
 | 
				
			||||||
			typ := c.expr(it.cond)
 | 
								typ := c.expr(it.cond)
 | 
				
			||||||
			typ_idx := table.type_idx(typ)
 | 
								typ_idx := typ.idx()
 | 
				
			||||||
			if it.is_range {
 | 
								if it.is_range {
 | 
				
			||||||
				high_type_idx := table.type_idx(c.expr(it.high))
 | 
									high_type_idx := c.expr(it.high).idx()
 | 
				
			||||||
				if typ_idx in table.integer_type_idxs && high_type_idx !in table.integer_type_idxs {
 | 
									if typ_idx in table.integer_type_idxs && high_type_idx !in table.integer_type_idxs {
 | 
				
			||||||
					c.error('range types do not match', it.cond.position())
 | 
										c.error('range types do not match', it.cond.position())
 | 
				
			||||||
				} else if typ_idx in table.float_type_idxs || high_type_idx in table.float_type_idxs {
 | 
									} else if typ_idx in table.float_type_idxs || high_type_idx in table.float_type_idxs {
 | 
				
			||||||
| 
						 | 
					@ -1342,11 +1342,11 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
 | 
				
			||||||
		ast.PrefixExpr {
 | 
							ast.PrefixExpr {
 | 
				
			||||||
			right_type := c.expr(it.right)
 | 
								right_type := c.expr(it.right)
 | 
				
			||||||
			// TODO: testing ref/deref strategy
 | 
								// TODO: testing ref/deref strategy
 | 
				
			||||||
			if it.op == .amp && !table.type_is_ptr(right_type) {
 | 
								if it.op == .amp && !right_type.is_ptr() {
 | 
				
			||||||
				return table.type_to_ptr(right_type)
 | 
									return right_type.to_ptr()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if it.op == .mul && table.type_is_ptr(right_type) {
 | 
								if it.op == .mul && right_type.is_ptr() {
 | 
				
			||||||
				return table.type_deref(right_type)
 | 
									return right_type.deref()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if it.op == .not && right_type != table.bool_type_idx {
 | 
								if it.op == .not && right_type != table.bool_type_idx {
 | 
				
			||||||
				c.error('! operator can only be used with bool types', it.pos)
 | 
									c.error('! operator can only be used with bool types', it.pos)
 | 
				
			||||||
| 
						 | 
					@ -1442,7 +1442,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
 | 
				
			||||||
					if typ == 0 {
 | 
										if typ == 0 {
 | 
				
			||||||
						typ = c.expr(it.expr)
 | 
											typ = c.expr(it.expr)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					is_optional := table.type_is(typ, .optional)
 | 
										is_optional := typ.flag_is(.optional)
 | 
				
			||||||
					ident.kind = .variable
 | 
										ident.kind = .variable
 | 
				
			||||||
					ident.info = ast.IdentVar{
 | 
										ident.info = ast.IdentVar{
 | 
				
			||||||
						typ: typ
 | 
											typ: typ
 | 
				
			||||||
| 
						 | 
					@ -1451,7 +1451,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
 | 
				
			||||||
					it.typ = typ
 | 
										it.typ = typ
 | 
				
			||||||
					// unwrap optional (`println(x)`)
 | 
										// unwrap optional (`println(x)`)
 | 
				
			||||||
					if is_optional {
 | 
										if is_optional {
 | 
				
			||||||
						return table.type_set(typ, .unset)
 | 
											return typ.set_flag(.unset)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return typ
 | 
										return typ
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -1646,7 +1646,7 @@ pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
 | 
				
			||||||
		if i < node.branches.len - 1 || !node.has_else {
 | 
							if i < node.branches.len - 1 || !node.has_else {
 | 
				
			||||||
			typ_sym := c.table.get_type_symbol(typ)
 | 
								typ_sym := c.table.get_type_symbol(typ)
 | 
				
			||||||
			// if typ_sym.kind != .bool {
 | 
								// if typ_sym.kind != .bool {
 | 
				
			||||||
			if table.type_idx(typ) != table.bool_type_idx {
 | 
								if typ.idx() != table.bool_type_idx {
 | 
				
			||||||
				c.error('non-bool (`$typ_sym.name`) used as if condition', node.pos)
 | 
									c.error('non-bool (`$typ_sym.name`) used as if condition', node.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1681,7 +1681,7 @@ pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
	typ := c.expr(node.expr)
 | 
						typ := c.expr(node.expr)
 | 
				
			||||||
	typ_sym := c.table.get_type_symbol(typ)
 | 
						typ_sym := c.table.get_type_symbol(typ)
 | 
				
			||||||
	// if !table.is_number(typ) {
 | 
						// if !typ.is_number() {
 | 
				
			||||||
	if !typ_sym.is_number() {
 | 
						if !typ_sym.is_number() {
 | 
				
			||||||
		println(typ_sym.kind.str())
 | 
							println(typ_sym.kind.str())
 | 
				
			||||||
		c.error('invalid operation: $node.op.str() (non-numeric type `$typ_sym.name`)', node.pos)
 | 
							c.error('invalid operation: $node.op.str() (non-numeric type `$typ_sym.name`)', node.pos)
 | 
				
			||||||
| 
						 | 
					@ -1712,11 +1712,11 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
 | 
				
			||||||
		// println('index expr left=$typ_sym.name $node.pos.line_nr')
 | 
							// println('index expr left=$typ_sym.name $node.pos.line_nr')
 | 
				
			||||||
		// if typ_sym.kind == .array && (!(table.type_idx(index_type) in table.number_type_idxs) &&
 | 
							// if typ_sym.kind == .array && (!(table.type_idx(index_type) in table.number_type_idxs) &&
 | 
				
			||||||
		// index_type_sym.kind != .enum_) {
 | 
							// index_type_sym.kind != .enum_) {
 | 
				
			||||||
		if typ_sym.kind in [.array, .array_fixed] && !(table.is_number(index_type) || index_type_sym.kind ==
 | 
							if typ_sym.kind in [.array, .array_fixed] && !(index_type.is_number() || index_type_sym.kind ==
 | 
				
			||||||
			.enum_) {
 | 
								.enum_) {
 | 
				
			||||||
			c.error('non-integer index `$index_type_sym.name` (array type `$typ_sym.name`)',
 | 
								c.error('non-integer index `$index_type_sym.name` (array type `$typ_sym.name`)',
 | 
				
			||||||
				node.pos)
 | 
									node.pos)
 | 
				
			||||||
		} else if typ_sym.kind == .map && table.type_idx(index_type) != table.string_type_idx {
 | 
							} else if typ_sym.kind == .map && index_type.idx() != table.string_type_idx {
 | 
				
			||||||
			c.error('non-string map index (map type `$typ_sym.name`)', node.pos)
 | 
								c.error('non-string map index (map type `$typ_sym.name`)', node.pos)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		value_type := c.table.value_type(typ)
 | 
							value_type := c.table.value_type(typ)
 | 
				
			||||||
| 
						 | 
					@ -1740,7 +1740,7 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
 | 
				
			||||||
// with this value.
 | 
					// with this value.
 | 
				
			||||||
pub fn (c mut Checker) enum_val(node mut ast.EnumVal) table.Type {
 | 
					pub fn (c mut Checker) enum_val(node mut ast.EnumVal) table.Type {
 | 
				
			||||||
	typ_idx := if node.enum_name == '' {
 | 
						typ_idx := if node.enum_name == '' {
 | 
				
			||||||
		table.type_idx(c.expected_type)
 | 
							c.expected_type.idx()
 | 
				
			||||||
	} else {		//
 | 
						} else {		//
 | 
				
			||||||
		c.table.find_type_idx(node.enum_name)
 | 
							c.table.find_type_idx(node.enum_name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -237,10 +237,10 @@ pub fn (mut g Gen) write_typeof_functions() {
 | 
				
			||||||
// V type to C type
 | 
					// V type to C type
 | 
				
			||||||
pub fn (mut g Gen) typ(t table.Type) string {
 | 
					pub fn (mut g Gen) typ(t table.Type) string {
 | 
				
			||||||
	mut styp := g.base_typ(t)
 | 
						mut styp := g.base_typ(t)
 | 
				
			||||||
	if table.type_is(t, .optional) {
 | 
						if t.flag_is(.optional) {
 | 
				
			||||||
		// Register an optional
 | 
							// Register an optional
 | 
				
			||||||
		styp = 'Option_' + styp
 | 
							styp = 'Option_' + styp
 | 
				
			||||||
		if table.type_is_ptr(t) {
 | 
							if t.is_ptr() {
 | 
				
			||||||
			styp = styp.replace('*', '_ptr')
 | 
								styp = styp.replace('*', '_ptr')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !(styp in g.optionals) {
 | 
							if !(styp in g.optionals) {
 | 
				
			||||||
| 
						 | 
					@ -254,7 +254,7 @@ pub fn (mut g Gen) typ(t table.Type) string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut g Gen) base_typ(t table.Type) string {
 | 
					pub fn (mut g Gen) base_typ(t table.Type) string {
 | 
				
			||||||
	nr_muls := table.type_nr_muls(t)
 | 
						nr_muls := t.nr_muls()
 | 
				
			||||||
	sym := g.table.get_type_symbol(t)
 | 
						sym := g.table.get_type_symbol(t)
 | 
				
			||||||
	mut styp := sym.name.replace('.', '__')
 | 
						mut styp := sym.name.replace('.', '__')
 | 
				
			||||||
	if nr_muls > 0 {
 | 
						if nr_muls > 0 {
 | 
				
			||||||
| 
						 | 
					@ -615,7 +615,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
 | 
				
			||||||
		// `for num in nums {`
 | 
							// `for num in nums {`
 | 
				
			||||||
		g.writeln('// FOR IN array')
 | 
							g.writeln('// FOR IN array')
 | 
				
			||||||
		styp := g.typ(it.val_type)
 | 
							styp := g.typ(it.val_type)
 | 
				
			||||||
		cond_type_is_ptr := table.type_is_ptr(it.cond_type)
 | 
							cond_type_is_ptr := it.cond_type.is_ptr()
 | 
				
			||||||
		atmp := g.new_tmp_var()
 | 
							atmp := g.new_tmp_var()
 | 
				
			||||||
		atmp_type := if cond_type_is_ptr { 'array *' } else { 'array' }
 | 
							atmp_type := if cond_type_is_ptr { 'array *' } else { 'array' }
 | 
				
			||||||
		g.write('${atmp_type} ${atmp} = ')
 | 
							g.write('${atmp_type} ${atmp} = ')
 | 
				
			||||||
| 
						 | 
					@ -650,7 +650,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		g.stmts(it.stmts)
 | 
							g.stmts(it.stmts)
 | 
				
			||||||
		g.writeln('}')
 | 
							g.writeln('}')
 | 
				
			||||||
	} else if table.type_is(it.cond_type, .variadic) {
 | 
						} else if it.cond_type.flag_is(.variadic) {
 | 
				
			||||||
		g.writeln('// FOR IN cond_type/variadic')
 | 
							g.writeln('// FOR IN cond_type/variadic')
 | 
				
			||||||
		i := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
 | 
							i := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
 | 
				
			||||||
		styp := g.typ(it.cond_type)
 | 
							styp := g.typ(it.cond_type)
 | 
				
			||||||
| 
						 | 
					@ -688,7 +688,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, exp_type table.Type) {
 | 
				
			||||||
				got_sym := g.table.get_type_symbol(got_type)
 | 
									got_sym := g.table.get_type_symbol(got_type)
 | 
				
			||||||
				got_styp := g.typ(got_type)
 | 
									got_styp := g.typ(got_type)
 | 
				
			||||||
				exp_styp := g.typ(exp_type)
 | 
									exp_styp := g.typ(exp_type)
 | 
				
			||||||
				got_idx := table.type_idx(got_type)
 | 
									got_idx := got_type.idx()
 | 
				
			||||||
				g.write('/* sum type cast */ ($exp_styp) {.obj = memdup(&(${got_styp}[]) {')
 | 
									g.write('/* sum type cast */ ($exp_styp) {.obj = memdup(&(${got_styp}[]) {')
 | 
				
			||||||
				g.expr(expr)
 | 
									g.expr(expr)
 | 
				
			||||||
				g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}')
 | 
									g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}')
 | 
				
			||||||
| 
						 | 
					@ -745,7 +745,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
 | 
				
			||||||
			or_stmts = it.or_block.stmts
 | 
								or_stmts = it.or_block.stmts
 | 
				
			||||||
			return_type = it.return_type
 | 
								return_type = it.return_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		is_optional := table.type_is(return_type, .optional)
 | 
							is_optional := return_type.flag_is(.optional)
 | 
				
			||||||
		mr_var_name := 'mr_$assign_stmt.pos.pos'
 | 
							mr_var_name := 'mr_$assign_stmt.pos.pos'
 | 
				
			||||||
		mr_styp := g.typ(return_type)
 | 
							mr_styp := g.typ(return_type)
 | 
				
			||||||
		g.write('$mr_styp $mr_var_name = ')
 | 
							g.write('$mr_styp $mr_var_name = ')
 | 
				
			||||||
| 
						 | 
					@ -802,7 +802,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else {}
 | 
									else {}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			gen_or := is_call && table.type_is(return_type, .optional)
 | 
								gen_or := is_call && return_type.flag_is(.optional)
 | 
				
			||||||
			g.is_assign_rhs = true
 | 
								g.is_assign_rhs = true
 | 
				
			||||||
			if ident.kind == .blank_ident {
 | 
								if ident.kind == .blank_ident {
 | 
				
			||||||
				if is_call {
 | 
									if is_call {
 | 
				
			||||||
| 
						 | 
					@ -893,7 +893,7 @@ fn (mut g Gen) free_scope_vars(pos int) {
 | 
				
			||||||
				// }
 | 
									// }
 | 
				
			||||||
				v := *it
 | 
									v := *it
 | 
				
			||||||
				sym := g.table.get_type_symbol(v.typ)
 | 
									sym := g.table.get_type_symbol(v.typ)
 | 
				
			||||||
				is_optional := table.type_is(v.typ, .optional)
 | 
									is_optional := v.typ.flag_is(.optional)
 | 
				
			||||||
				if sym.kind == .array && !is_optional {
 | 
									if sym.kind == .array && !is_optional {
 | 
				
			||||||
					g.writeln('array_free($v.name); // autofreed')
 | 
										g.writeln('array_free($v.name); // autofreed')
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -966,7 +966,7 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
				
			||||||
				g.out.go_back(1)
 | 
									g.out.go_back(1)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sym := g.table.get_type_symbol(it.typ)
 | 
								sym := g.table.get_type_symbol(it.typ)
 | 
				
			||||||
			if sym.kind == .string && !table.type_is_ptr(it.typ) {
 | 
								if sym.kind == .string && !it.typ.is_ptr() {
 | 
				
			||||||
				// `string(x)` needs `tos()`, but not `&string(x)
 | 
									// `string(x)` needs `tos()`, but not `&string(x)
 | 
				
			||||||
				// `tos(str, len)`, `tos2(str)`
 | 
									// `tos(str, len)`, `tos2(str)`
 | 
				
			||||||
				if it.has_arg {
 | 
									if it.has_arg {
 | 
				
			||||||
| 
						 | 
					@ -1113,8 +1113,8 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ast.SelectorExpr {
 | 
							ast.SelectorExpr {
 | 
				
			||||||
			g.expr(it.expr)
 | 
								g.expr(it.expr)
 | 
				
			||||||
			// if table.type_nr_muls(it.expr_type) > 0 {
 | 
								// if it.expr_type.nr_muls() > 0 {
 | 
				
			||||||
			if table.type_is_ptr(it.expr_type) {
 | 
								if it.expr_type.is_ptr() {
 | 
				
			||||||
				g.write('->')
 | 
									g.write('->')
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				// g.write('. /*typ=  $it.expr_type */') // ${g.typ(it.expr_type)} /')
 | 
									// g.write('. /*typ=  $it.expr_type */') // ${g.typ(it.expr_type)} /')
 | 
				
			||||||
| 
						 | 
					@ -1128,7 +1128,7 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
				
			||||||
		ast.Type {
 | 
							ast.Type {
 | 
				
			||||||
			// match sum Type
 | 
								// match sum Type
 | 
				
			||||||
			// g.write('/* Type */')
 | 
								// g.write('/* Type */')
 | 
				
			||||||
			type_idx := table.type_idx(it.typ)
 | 
								type_idx := it.typ.idx()
 | 
				
			||||||
			sym := g.table.get_type_symbol(it.typ)
 | 
								sym := g.table.get_type_symbol(it.typ)
 | 
				
			||||||
			g.write('$type_idx /* $sym.name */')
 | 
								g.write('$type_idx /* $sym.name */')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1159,7 +1159,7 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) {
 | 
				
			||||||
	if sym.kind == .sum_type {
 | 
						if sym.kind == .sum_type {
 | 
				
			||||||
		// When encountering a .sum_type, typeof() should be done at runtime,
 | 
							// When encountering a .sum_type, typeof() should be done at runtime,
 | 
				
			||||||
		// because the subtype of the expression may change:
 | 
							// because the subtype of the expression may change:
 | 
				
			||||||
		sum_type_idx := table.type_idx(node.expr_type)
 | 
							sum_type_idx := node.expr_type.idx()
 | 
				
			||||||
		g.write('tos3( /* ${sym.name} */ v_typeof_sumtype_${sum_type_idx}( (')
 | 
							g.write('tos3( /* ${sym.name} */ v_typeof_sumtype_${sum_type_idx}( (')
 | 
				
			||||||
		g.expr(node.expr)
 | 
							g.expr(node.expr)
 | 
				
			||||||
		g.write(').typ ))')
 | 
							g.write(').typ ))')
 | 
				
			||||||
| 
						 | 
					@ -1207,7 +1207,7 @@ fn (mut g Gen) assign_expr(node ast.AssignExpr) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {}
 | 
							else {}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	gen_or := is_call && table.type_is(return_type, .optional)
 | 
						gen_or := is_call && return_type.flag_is(.optional)
 | 
				
			||||||
	tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
 | 
						tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
 | 
				
			||||||
	if gen_or {
 | 
						if gen_or {
 | 
				
			||||||
		rstyp := g.typ(return_type)
 | 
							rstyp := g.typ(return_type)
 | 
				
			||||||
| 
						 | 
					@ -1225,7 +1225,7 @@ fn (mut g Gen) assign_expr(node ast.AssignExpr) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		g.is_assign_lhs = true
 | 
							g.is_assign_lhs = true
 | 
				
			||||||
		if table.type_is(node.right_type, .optional) {
 | 
							if node.right_type.flag_is(.optional) {
 | 
				
			||||||
			g.right_is_opt = true
 | 
								g.right_is_opt = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		mut str_add := false
 | 
							mut str_add := false
 | 
				
			||||||
| 
						 | 
					@ -1390,8 +1390,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
 | 
				
			||||||
			g.expr_with_cast(node.right, node.right_type, info.elem_type)
 | 
								g.expr_with_cast(node.right, node.right_type, info.elem_type)
 | 
				
			||||||
			g.write(' })')
 | 
								g.write(' })')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (node.left_type == node.right_type) && table.is_float(node.left_type) && node.op in
 | 
						} else if (node.left_type == node.right_type) && node.left_type.is_float() && node.op in [.eq, .ne] {
 | 
				
			||||||
		[.eq, .ne] {
 | 
					 | 
				
			||||||
		// floats should be compared with epsilon
 | 
							// floats should be compared with epsilon
 | 
				
			||||||
		if node.left_type == table.f64_type_idx {
 | 
							if node.left_type == table.f64_type_idx {
 | 
				
			||||||
			if node.op == .eq {
 | 
								if node.op == .eq {
 | 
				
			||||||
| 
						 | 
					@ -1687,8 +1686,8 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !is_range {
 | 
						if !is_range {
 | 
				
			||||||
		sym := g.table.get_type_symbol(node.left_type)
 | 
							sym := g.table.get_type_symbol(node.left_type)
 | 
				
			||||||
		left_is_ptr := table.type_is_ptr(node.left_type)
 | 
							left_is_ptr := node.left_type.is_ptr()
 | 
				
			||||||
		if table.type_is(node.left_type, .variadic) {
 | 
							if node.left_type.flag_is(.variadic) {
 | 
				
			||||||
			g.expr(node.left)
 | 
								g.expr(node.left)
 | 
				
			||||||
			g.write('.args')
 | 
								g.write('.args')
 | 
				
			||||||
			g.write('[')
 | 
								g.write('[')
 | 
				
			||||||
| 
						 | 
					@ -1789,7 +1788,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
 | 
				
			||||||
				g.expr(node.index)
 | 
									g.expr(node.index)
 | 
				
			||||||
				g.write(', &($elem_type_str[]){ $zero }))')
 | 
									g.write(', &($elem_type_str[]){ $zero }))')
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if sym.kind == .string && !table.type_is_ptr(node.left_type) {
 | 
							} else if sym.kind == .string && !node.left_type.is_ptr() {
 | 
				
			||||||
			g.write('string_at(')
 | 
								g.write('string_at(')
 | 
				
			||||||
			g.expr(node.left)
 | 
								g.expr(node.left)
 | 
				
			||||||
			g.write(', ')
 | 
								g.write(', ')
 | 
				
			||||||
| 
						 | 
					@ -1810,14 +1809,14 @@ fn (mut g Gen) return_statement(node ast.Return) {
 | 
				
			||||||
		g.writeln(' 0;')
 | 
							g.writeln(' 0;')
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fn_return_is_optional := table.type_is(g.fn_decl.return_type, .optional)
 | 
						fn_return_is_optional := g.fn_decl.return_type.flag_is(.optional)
 | 
				
			||||||
	// multiple returns
 | 
						// multiple returns
 | 
				
			||||||
	if node.exprs.len > 1 {
 | 
						if node.exprs.len > 1 {
 | 
				
			||||||
		g.write(' ')
 | 
							g.write(' ')
 | 
				
			||||||
		// typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
 | 
							// typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
 | 
				
			||||||
		// mr_info := typ_sym.info as table.MultiReturn
 | 
							// mr_info := typ_sym.info as table.MultiReturn
 | 
				
			||||||
		mut styp := ''
 | 
							mut styp := ''
 | 
				
			||||||
		if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] !=
 | 
							if fn_return_is_optional { // && !node.types[0].flag_is(.optional) && node.types[0] !=
 | 
				
			||||||
			styp = g.base_typ(g.fn_decl.return_type)
 | 
								styp = g.base_typ(g.fn_decl.return_type)
 | 
				
			||||||
			g.write('opt_ok(&($styp/*X*/[]) { ')
 | 
								g.write('opt_ok(&($styp/*X*/[]) { ')
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					@ -1840,7 +1839,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
 | 
				
			||||||
		g.write(' ')
 | 
							g.write(' ')
 | 
				
			||||||
		return_sym := g.table.get_type_symbol(node.types[0])
 | 
							return_sym := g.table.get_type_symbol(node.types[0])
 | 
				
			||||||
		// `return opt_ok(expr)` for functions that expect an optional
 | 
							// `return opt_ok(expr)` for functions that expect an optional
 | 
				
			||||||
		if fn_return_is_optional && !table.type_is(node.types[0], .optional) && return_sym.name !=
 | 
							if fn_return_is_optional && !node.types[0].flag_is(.optional) && return_sym.name !=
 | 
				
			||||||
			'Option' {
 | 
								'Option' {
 | 
				
			||||||
			mut is_none := false
 | 
								mut is_none := false
 | 
				
			||||||
			mut is_error := false
 | 
								mut is_error := false
 | 
				
			||||||
| 
						 | 
					@ -1865,7 +1864,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// g.write('/*OPTIONAL*/')
 | 
								// g.write('/*OPTIONAL*/')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !table.type_is_ptr(g.fn_decl.return_type) && table.type_is_ptr(node.types[0]) {
 | 
							if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() {
 | 
				
			||||||
			// Automatic Dereference
 | 
								// Automatic Dereference
 | 
				
			||||||
			g.write('*')
 | 
								g.write('*')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1978,7 +1977,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
				
			||||||
			if field.name in inited_fields {
 | 
								if field.name in inited_fields {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if table.type_is(field.typ, .optional) {
 | 
								if field.typ.flag_is(.optional) {
 | 
				
			||||||
				// TODO handle/require optionals in inits
 | 
									// TODO handle/require optionals in inits
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -2236,7 +2235,7 @@ fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
 | 
				
			||||||
				for field in info.fields {
 | 
									for field in info.fields {
 | 
				
			||||||
					dep := g.table.get_type_symbol(field.typ).name
 | 
										dep := g.table.get_type_symbol(field.typ).name
 | 
				
			||||||
					// skip if not in types list or already in deps
 | 
										// skip if not in types list or already in deps
 | 
				
			||||||
					if !(dep in type_names) || dep in field_deps || table.type_is_ptr(field.typ) {
 | 
										if !(dep in type_names) || dep in field_deps || field.typ.is_ptr() {
 | 
				
			||||||
						continue
 | 
											continue
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					field_deps << dep
 | 
										field_deps << dep
 | 
				
			||||||
| 
						 | 
					@ -2664,7 +2663,7 @@ fn (g Gen) type_default(typ table.Type) string {
 | 
				
			||||||
		return 'new_map_1(sizeof($value_type_str))'
 | 
							return 'new_map_1(sizeof($value_type_str))'
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Always set pointers to 0
 | 
						// Always set pointers to 0
 | 
				
			||||||
	if table.type_is_ptr(typ) {
 | 
						if typ.is_ptr() {
 | 
				
			||||||
		return '0'
 | 
							return '0'
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// User struct defined in another module.
 | 
						// User struct defined in another module.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	if it.is_method {
 | 
						if it.is_method {
 | 
				
			||||||
		mut styp := g.typ(it.receiver.typ)
 | 
							mut styp := g.typ(it.receiver.typ)
 | 
				
			||||||
		// if table.type_nr_muls(it.receiver.typ) > 0 {
 | 
							// if it.receiver.typ.nr_muls() > 0 {
 | 
				
			||||||
		// if it.rec_mut {
 | 
							// if it.rec_mut {
 | 
				
			||||||
		// styp += '*'
 | 
							// styp += '*'
 | 
				
			||||||
		// }
 | 
							// }
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) {
 | 
				
			||||||
			g.write(arg_type_name)
 | 
								g.write(arg_type_name)
 | 
				
			||||||
			g.definitions.write(arg_type_name)
 | 
								g.definitions.write(arg_type_name)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			mut nr_muls := table.type_nr_muls(arg.typ)
 | 
								mut nr_muls := arg.typ.nr_muls()
 | 
				
			||||||
			s := arg_type_name + ' ' + arg.name
 | 
								s := arg_type_name + ' ' + arg.name
 | 
				
			||||||
			if arg.is_mut {
 | 
								if arg.is_mut {
 | 
				
			||||||
				// mut arg needs one *
 | 
									// mut arg needs one *
 | 
				
			||||||
| 
						 | 
					@ -235,17 +235,17 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
 | 
				
			||||||
	// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
 | 
						// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
 | 
				
			||||||
	// }
 | 
						// }
 | 
				
			||||||
	g.write('${name}(')
 | 
						g.write('${name}(')
 | 
				
			||||||
	if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) {
 | 
						if node.receiver_type.is_ptr() && !node.left_type.is_ptr() {
 | 
				
			||||||
		// The receiver is a reference, but the caller provided a value
 | 
							// The receiver is a reference, but the caller provided a value
 | 
				
			||||||
		// Add `&` automatically.
 | 
							// Add `&` automatically.
 | 
				
			||||||
		// TODO same logic in call_args()
 | 
							// TODO same logic in call_args()
 | 
				
			||||||
		g.write('&')
 | 
							g.write('&')
 | 
				
			||||||
	} else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) {
 | 
						} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() {
 | 
				
			||||||
		g.write('/*rec*/*')
 | 
							g.write('/*rec*/*')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	g.expr(node.left)
 | 
						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 && 
 | 
				
			||||||
		1], .variadic)
 | 
							node.expected_arg_types[node.expected_arg_types.len -1].flag_is(.variadic)
 | 
				
			||||||
	if node.args.len > 0 || is_variadic {
 | 
						if node.args.len > 0 || is_variadic {
 | 
				
			||||||
		g.write(', ')
 | 
							g.write(', ')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -275,7 +275,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
 | 
				
			||||||
	// will be `0` for `foo()`
 | 
						// will be `0` for `foo()`
 | 
				
			||||||
	if node.left_type != 0 {
 | 
						if node.left_type != 0 {
 | 
				
			||||||
		g.expr(node.left)
 | 
							g.expr(node.left)
 | 
				
			||||||
		if table.type_is_ptr(node.left_type) {
 | 
							if node.left_type.is_ptr() {
 | 
				
			||||||
			g.write('->')
 | 
								g.write('->')
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			g.write('.')
 | 
								g.write('.')
 | 
				
			||||||
| 
						 | 
					@ -319,12 +319,12 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
 | 
				
			||||||
		typ := node.args[0].typ
 | 
							typ := node.args[0].typ
 | 
				
			||||||
		mut styp := g.typ(typ)
 | 
							mut styp := g.typ(typ)
 | 
				
			||||||
		sym := g.table.get_type_symbol(typ)
 | 
							sym := g.table.get_type_symbol(typ)
 | 
				
			||||||
		if table.type_is_ptr(typ) {
 | 
							if typ.is_ptr() {
 | 
				
			||||||
			styp = styp.replace('*', '')
 | 
								styp = styp.replace('*', '')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		mut str_fn_name := styp_to_str_fn_name(styp)
 | 
							mut str_fn_name := styp_to_str_fn_name(styp)
 | 
				
			||||||
		g.gen_str_for_type(sym, styp, str_fn_name)
 | 
							g.gen_str_for_type(sym, styp, str_fn_name)
 | 
				
			||||||
		if g.autofree && !table.type_is(typ, .optional) {
 | 
							if g.autofree && !typ.flag_is(.optional) {
 | 
				
			||||||
			// Create a temporary variable so that the value can be freed
 | 
								// Create a temporary variable so that the value can be freed
 | 
				
			||||||
			tmp := g.new_tmp_var()
 | 
								tmp := g.new_tmp_var()
 | 
				
			||||||
			// tmps << tmp
 | 
								// tmps << tmp
 | 
				
			||||||
| 
						 | 
					@ -338,7 +338,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
 | 
				
			||||||
				ast.Ident { true }
 | 
									ast.Ident { true }
 | 
				
			||||||
				else { false }
 | 
									else { false }
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if table.type_is_ptr(typ) && sym.kind != .struct_ {
 | 
								if typ.is_ptr() && sym.kind != .struct_ {
 | 
				
			||||||
				// ptr_str() for pointers
 | 
									// ptr_str() for pointers
 | 
				
			||||||
				styp = 'ptr'
 | 
									styp = 'ptr'
 | 
				
			||||||
				str_fn_name = 'ptr_str'
 | 
									str_fn_name = 'ptr_str'
 | 
				
			||||||
| 
						 | 
					@ -350,7 +350,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
 | 
				
			||||||
					// when no var, print string directly
 | 
										// when no var, print string directly
 | 
				
			||||||
					g.write('${print_method}(tos3("')
 | 
										g.write('${print_method}(tos3("')
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if table.type_is_ptr(typ) {
 | 
									if typ.is_ptr() {
 | 
				
			||||||
					// dereference
 | 
										// dereference
 | 
				
			||||||
					g.write('*')
 | 
										g.write('*')
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -361,7 +361,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				g.write('${print_method}(${str_fn_name}(')
 | 
									g.write('${print_method}(${str_fn_name}(')
 | 
				
			||||||
				if table.type_is_ptr(typ) && sym.kind == .struct_ {
 | 
									if typ.is_ptr() && sym.kind == .struct_ {
 | 
				
			||||||
					// dereference
 | 
										// dereference
 | 
				
			||||||
					g.write('*')
 | 
										g.write('*')
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -388,9 +388,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
 | 
					fn (mut g 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 &&
 | 
				
			||||||
		1], .variadic)
 | 
							expected_types[expected_types.len - 1].flag_is(.variadic)
 | 
				
			||||||
	is_forwarding_varg := args.len > 0 && table.type_is(args[args.len - 1].typ, .variadic)
 | 
						is_forwarding_varg := args.len > 0 && args[args.len - 1].typ.flag_is(.variadic)
 | 
				
			||||||
	gen_vargs := is_variadic && !is_forwarding_varg
 | 
						gen_vargs := is_variadic && !is_forwarding_varg
 | 
				
			||||||
	mut arg_no := 0
 | 
						mut arg_no := 0
 | 
				
			||||||
	for arg in args {
 | 
						for arg in args {
 | 
				
			||||||
| 
						 | 
					@ -434,8 +434,8 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
 | 
					fn (mut g 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 := expected_type.is_ptr() || expected_type.idx() in table.pointer_type_idxs
 | 
				
			||||||
	expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs
 | 
						expr_is_ptr := arg.typ.is_ptr() || arg.typ.idx() in table.pointer_type_idxs
 | 
				
			||||||
	if arg.is_mut && !arg_is_ptr {
 | 
						if arg.is_mut && !arg_is_ptr {
 | 
				
			||||||
		g.write('&/*mut*/')
 | 
							g.write('&/*mut*/')
 | 
				
			||||||
	} else if arg_is_ptr && !expr_is_ptr {
 | 
						} else if arg_is_ptr && !expr_is_ptr {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -765,7 +765,7 @@ fn (g mut JsGen) gen_for_in_stmt(it ast.ForInStmt) {
 | 
				
			||||||
		g.inside_loop = false
 | 
							g.inside_loop = false
 | 
				
			||||||
		g.stmts(it.stmts)
 | 
							g.stmts(it.stmts)
 | 
				
			||||||
		g.writeln('}')
 | 
							g.writeln('}')
 | 
				
			||||||
	} else if it.kind == .array || table.type_is(it.cond_type, .variadic) {
 | 
						} else if it.kind == .array || it.cond_type.flag_is(.variadic) {
 | 
				
			||||||
		// `for num in nums {`
 | 
							// `for num in nums {`
 | 
				
			||||||
		i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var }
 | 
							i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var }
 | 
				
			||||||
		// styp := g.typ(it.val_type)
 | 
							// styp := g.typ(it.val_type)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -304,7 +304,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mut arg_type := p.parse_type()
 | 
								mut arg_type := p.parse_type()
 | 
				
			||||||
			if is_variadic {
 | 
								if is_variadic {
 | 
				
			||||||
				arg_type = table.type_set(arg_type, .variadic)
 | 
									arg_type = arg_type.set_flag(.variadic)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if p.tok.kind == .comma {
 | 
								if p.tok.kind == .comma {
 | 
				
			||||||
				if is_variadic {
 | 
									if is_variadic {
 | 
				
			||||||
| 
						 | 
					@ -337,7 +337,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mut typ := p.parse_type()
 | 
								mut typ := p.parse_type()
 | 
				
			||||||
			if is_variadic {
 | 
								if is_variadic {
 | 
				
			||||||
				typ = table.type_set(typ, .variadic)
 | 
									typ = typ.set_flag(.variadic)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			for arg_name in arg_names {
 | 
								for arg_name in arg_names {
 | 
				
			||||||
				args << table.Arg{
 | 
									args << table.Arg{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
 | 
				
			||||||
			exprs << expr
 | 
								exprs << expr
 | 
				
			||||||
			p.scope.register('it', ast.Var{
 | 
								p.scope.register('it', ast.Var{
 | 
				
			||||||
				name: 'it'
 | 
									name: 'it'
 | 
				
			||||||
				typ: table.type_to_ptr(typ)
 | 
									typ: typ.to_ptr()
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			// TODO
 | 
								// TODO
 | 
				
			||||||
			if p.tok.kind == .comma {
 | 
								if p.tok.kind == .comma {
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
 | 
				
			||||||
				// TODO doesn't work right now
 | 
									// TODO doesn't work right now
 | 
				
			||||||
				p.scope.register(var_name, ast.Var{
 | 
									p.scope.register(var_name, ast.Var{
 | 
				
			||||||
					name: var_name
 | 
										name: var_name
 | 
				
			||||||
					typ: table.type_to_ptr(typ)
 | 
										typ: typ.to_ptr()
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				// println(var_name)
 | 
									// println(var_name)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ pub fn (mut p Parser) parse_map_type() table.Type {
 | 
				
			||||||
	key_type := p.parse_type()
 | 
						key_type := p.parse_type()
 | 
				
			||||||
	// key_type_sym := p.get_type_symbol(key_type)
 | 
						// key_type_sym := p.get_type_symbol(key_type)
 | 
				
			||||||
	// if key_type_sym.kind != .string {
 | 
						// if key_type_sym.kind != .string {
 | 
				
			||||||
	if table.type_idx(key_type) != table.string_type_idx {
 | 
						if key_type.idx() != table.string_type_idx {
 | 
				
			||||||
		p.error('maps can only have string keys for now')
 | 
							p.error('maps can only have string keys for now')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p.check(.rsbr)
 | 
						p.check(.rsbr)
 | 
				
			||||||
| 
						 | 
					@ -121,7 +121,7 @@ pub fn (mut p Parser) parse_type() table.Type {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mut typ := p.parse_any_type(is_c, is_js, nr_muls > 0)
 | 
						mut typ := p.parse_any_type(is_c, is_js, nr_muls > 0)
 | 
				
			||||||
	if is_optional {
 | 
						if is_optional {
 | 
				
			||||||
		typ = table.type_set(typ, .optional)
 | 
							typ = typ.set_flag(.optional)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if nr_muls > 0 {
 | 
						if nr_muls > 0 {
 | 
				
			||||||
		typ = table.type_set_nr_muls(typ, nr_muls)
 | 
							typ = table.type_set_nr_muls(typ, nr_muls)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -632,7 +632,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
 | 
				
			||||||
			mut to_typ := p.parse_type()
 | 
								mut to_typ := p.parse_type()
 | 
				
			||||||
			if p.is_amp {
 | 
								if p.is_amp {
 | 
				
			||||||
				// Handle `&Foo(0)`
 | 
									// Handle `&Foo(0)`
 | 
				
			||||||
				to_typ = table.type_to_ptr(to_typ)
 | 
									to_typ = to_typ.to_ptr()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			p.check(.lpar)
 | 
								p.check(.lpar)
 | 
				
			||||||
			mut expr := ast.Expr{}
 | 
								mut expr := ast.Expr{}
 | 
				
			||||||
| 
						 | 
					@ -640,7 +640,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
 | 
				
			||||||
			mut has_arg := false
 | 
								mut has_arg := false
 | 
				
			||||||
			expr = p.expr(0)
 | 
								expr = p.expr(0)
 | 
				
			||||||
			// TODO, string(b, len)
 | 
								// TODO, string(b, len)
 | 
				
			||||||
			if p.tok.kind == .comma && table.type_idx(to_typ) == table.string_type_idx {
 | 
								if p.tok.kind == .comma && to_typ.idx() == table.string_type_idx {
 | 
				
			||||||
				p.check(.comma)
 | 
									p.check(.comma)
 | 
				
			||||||
				arg = p.expr(0) // len
 | 
									arg = p.expr(0) // len
 | 
				
			||||||
				has_arg = true
 | 
									has_arg = true
 | 
				
			||||||
| 
						 | 
					@ -1192,7 +1192,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// type MyType int
 | 
						// type MyType int
 | 
				
			||||||
	parent_type := first_type
 | 
						parent_type := first_type
 | 
				
			||||||
	pid := table.type_idx(parent_type)
 | 
						pid := parent_type.idx()
 | 
				
			||||||
	p.table.register_type_symbol(table.TypeSymbol{
 | 
						p.table.register_type_symbol(table.TypeSymbol{
 | 
				
			||||||
		kind: .alias
 | 
							kind: .alias
 | 
				
			||||||
		name: p.prepend_mod(name)
 | 
							name: p.prepend_mod(name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,19 +46,19 @@ pub fn (types []Type) contains(typ Type) bool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// return TypeSymbol idx for `t`
 | 
					// return TypeSymbol idx for `t`
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_idx(t Type) int {
 | 
					pub fn (t Type) idx() int {
 | 
				
			||||||
	return u16(t) & 0xffff
 | 
						return u16(t) & 0xffff
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// return nr_muls for `t`
 | 
					// return nr_muls for `t`
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_nr_muls(t Type) int {
 | 
					pub fn (t Type) nr_muls() int {
 | 
				
			||||||
	return (int(t) >> 16) & 0xff
 | 
						return (int(t) >> 16) & 0xff
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// return true if `t` is a pointer (nr_muls>0)
 | 
					// return true if `t` is a pointer (nr_muls>0)
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_is_ptr(t Type) bool {
 | 
					pub fn (t Type) is_ptr() bool {
 | 
				
			||||||
	return (int(t) >> 16) & 0xff > 0
 | 
						return (int(t) >> 16) & 0xff > 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ pub fn type_set_nr_muls(t Type, nr_muls int) Type {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// increments nr_nuls on `t` and return it
 | 
					// increments nr_nuls on `t` and return it
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_to_ptr(t Type) Type {
 | 
					pub fn (t Type) to_ptr() Type {
 | 
				
			||||||
	nr_muls := (int(t) >> 16) & 0xff
 | 
						nr_muls := (int(t) >> 16) & 0xff
 | 
				
			||||||
	if nr_muls == 255 {
 | 
						if nr_muls == 255 {
 | 
				
			||||||
		panic('type_to_pre: nr_muls is already at max of 255')
 | 
							panic('type_to_pre: nr_muls is already at max of 255')
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ pub fn type_to_ptr(t Type) Type {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// decrement nr_muls on `t` and return it
 | 
					// decrement nr_muls on `t` and return it
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_deref(t Type) Type {
 | 
					pub fn (t Type) deref() Type {
 | 
				
			||||||
	nr_muls := (int(t) >> 16) & 0xff
 | 
						nr_muls := (int(t) >> 16) & 0xff
 | 
				
			||||||
	if nr_muls == 0 {
 | 
						if nr_muls == 0 {
 | 
				
			||||||
		panic('deref: type `$t` is not a pointer')
 | 
							panic('deref: type `$t` is not a pointer')
 | 
				
			||||||
| 
						 | 
					@ -93,19 +93,19 @@ pub fn type_deref(t Type) Type {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// return the flag that is set on `t`
 | 
					// return the flag that is set on `t`
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_flag(t Type) TypeFlag {
 | 
					pub fn (t Type) flag() TypeFlag {
 | 
				
			||||||
	return (int(t) >> 24) & 0xff
 | 
						return (int(t) >> 24) & 0xff
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// set the flag on `t` to `flag` and return it
 | 
					// set the flag on `t` to `flag` and return it
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_set(t Type, flag TypeFlag) Type {
 | 
					pub fn (t Type) set_flag(flag TypeFlag) Type {
 | 
				
			||||||
	return (int(flag) << 24) | (((int(t) >> 16) & 0xff) << 16) | (u16(t) & 0xffff)
 | 
						return (int(flag) << 24) | (((int(t) >> 16) & 0xff) << 16) | (u16(t) & 0xffff)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// return true if the flag set on `t` is `flag`
 | 
					// return true if the flag set on `t` is `flag`
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn type_is(t Type, flag TypeFlag) bool {
 | 
					pub fn (t Type) flag_is(flag TypeFlag) bool {
 | 
				
			||||||
	return (int(t) >> 24) & 0xff == flag
 | 
						return (int(t) >> 24) & 0xff == flag
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,18 +131,18 @@ pub fn new_type_ptr(idx, nr_muls int) Type {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn is_float(typ Type) bool {
 | 
					pub fn (typ Type) is_float() bool {
 | 
				
			||||||
	return type_idx(typ) in float_type_idxs
 | 
						return typ.idx() in float_type_idxs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn is_int(typ Type) bool {
 | 
					pub fn (typ Type) is_int() bool {
 | 
				
			||||||
	return type_idx(typ) in integer_type_idxs
 | 
						return typ.idx() in integer_type_idxs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn is_number(typ Type) bool {
 | 
					pub fn (typ Type) is_number() bool {
 | 
				
			||||||
	return type_idx(typ) in number_type_idxs
 | 
						return typ.idx() in number_type_idxs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const (
 | 
					pub const (
 | 
				
			||||||
| 
						 | 
					@ -580,11 +580,11 @@ pub fn (table &Table) type_to_str(t Type) string {
 | 
				
			||||||
			res = '[]' + res
 | 
								res = '[]' + res
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	nr_muls := type_nr_muls(t)
 | 
						nr_muls := t.nr_muls()
 | 
				
			||||||
	if nr_muls > 0 {
 | 
						if nr_muls > 0 {
 | 
				
			||||||
		res = strings.repeat(`&`, nr_muls) + res
 | 
							res = strings.repeat(`&`, nr_muls) + res
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if type_is(t, .optional) {
 | 
						if t.flag_is(.optional) {
 | 
				
			||||||
		res = '?' + res
 | 
							res = '?' + res
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -194,7 +194,7 @@ pub fn (t &Table) find_type(name string) ?TypeSymbol {
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
 | 
					pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
 | 
				
			||||||
	// println('get_type_symbol $typ')
 | 
						// println('get_type_symbol $typ')
 | 
				
			||||||
	idx := type_idx(typ)
 | 
						idx := typ.idx()
 | 
				
			||||||
	if idx > 0 {
 | 
						if idx > 0 {
 | 
				
			||||||
		return &t.types[idx]
 | 
							return &t.types[idx]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -272,7 +272,7 @@ pub fn (t &Table) known_type(name string) bool {
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
 | 
					pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
 | 
				
			||||||
	elem_type_sym := t.get_type_symbol(elem_type)
 | 
						elem_type_sym := t.get_type_symbol(elem_type)
 | 
				
			||||||
	return 'array_${elem_type_sym.name}' + if type_is_ptr(elem_type) {
 | 
						return 'array_${elem_type_sym.name}' + if elem_type.is_ptr() {
 | 
				
			||||||
		'_ptr'
 | 
							'_ptr'
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		''
 | 
							''
 | 
				
			||||||
| 
						 | 
					@ -286,7 +286,7 @@ pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn (t &Table) array_fixed_name(elem_type Type, size, nr_dims int) string {
 | 
					pub fn (t &Table) array_fixed_name(elem_type Type, size, nr_dims int) string {
 | 
				
			||||||
	elem_type_sym := t.get_type_symbol(elem_type)
 | 
						elem_type_sym := t.get_type_symbol(elem_type)
 | 
				
			||||||
	return 'array_fixed_${elem_type_sym.name}_${size}' + if type_is_ptr(elem_type) {
 | 
						return 'array_fixed_${elem_type_sym.name}_${size}' + if elem_type.is_ptr() {
 | 
				
			||||||
		'_ptr'
 | 
							'_ptr'
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		''
 | 
							''
 | 
				
			||||||
| 
						 | 
					@ -301,7 +301,7 @@ pub fn (t &Table) array_fixed_name(elem_type Type, size, nr_dims int) string {
 | 
				
			||||||
pub fn (t &Table) map_name(key_type, value_type Type) string {
 | 
					pub fn (t &Table) map_name(key_type, value_type Type) string {
 | 
				
			||||||
	key_type_sym := t.get_type_symbol(key_type)
 | 
						key_type_sym := t.get_type_symbol(key_type)
 | 
				
			||||||
	value_type_sym := t.get_type_symbol(value_type)
 | 
						value_type_sym := t.get_type_symbol(value_type)
 | 
				
			||||||
	suffix := if type_is_ptr(value_type) { '_ptr' } else { '' }
 | 
						suffix := if value_type.is_ptr() { '_ptr' } else { '' }
 | 
				
			||||||
	return 'map_${key_type_sym.name}_${value_type_sym.name}' + suffix
 | 
						return 'map_${key_type_sym.name}_${value_type_sym.name}' + suffix
 | 
				
			||||||
	// return 'map_${value_type_sym.name}' + suffix
 | 
						// return 'map_${value_type_sym.name}' + suffix
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -413,9 +413,9 @@ pub fn (mut t Table) add_placeholder_type(name string) int {
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn (t &Table) value_type(typ Type) Type {
 | 
					pub fn (t &Table) value_type(typ Type) Type {
 | 
				
			||||||
	typ_sym := t.get_type_symbol(typ)
 | 
						typ_sym := t.get_type_symbol(typ)
 | 
				
			||||||
	if type_is(typ, .variadic) {
 | 
						if typ.flag_is(.variadic) {
 | 
				
			||||||
		// ...string => string
 | 
							// ...string => string
 | 
				
			||||||
		return type_set(typ, .unset)
 | 
							return typ.set_flag(.unset)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if typ_sym.kind == .array {
 | 
						if typ_sym.kind == .array {
 | 
				
			||||||
		// Check index type
 | 
							// Check index type
 | 
				
			||||||
| 
						 | 
					@ -430,17 +430,17 @@ pub fn (t &Table) value_type(typ Type) Type {
 | 
				
			||||||
		info := typ_sym.info as Map
 | 
							info := typ_sym.info as Map
 | 
				
			||||||
		return info.value_type
 | 
							return info.value_type
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if typ_sym.kind == .string && type_is_ptr(typ) {
 | 
						if typ_sym.kind == .string && typ.is_ptr() {
 | 
				
			||||||
		// (&string)[i] => string
 | 
							// (&string)[i] => string
 | 
				
			||||||
		return string_type
 | 
							return string_type
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if typ_sym.kind in [.byteptr, .string] {
 | 
						if typ_sym.kind in [.byteptr, .string] {
 | 
				
			||||||
		return byte_type
 | 
							return byte_type
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if type_is_ptr(typ) {
 | 
						if typ.is_ptr() {
 | 
				
			||||||
		// byte* => byte
 | 
							// byte* => byte
 | 
				
			||||||
		// bytes[0] is a byte, not byte*
 | 
							// bytes[0] is a byte, not byte*
 | 
				
			||||||
		return type_deref(typ)
 | 
							return typ.deref()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: remove when map_string is removed
 | 
						// TODO: remove when map_string is removed
 | 
				
			||||||
	if typ_sym.name == 'map_string' {
 | 
						if typ_sym.name == 'map_string' {
 | 
				
			||||||
| 
						 | 
					@ -450,10 +450,10 @@ pub fn (t &Table) value_type(typ Type) Type {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (t &Table) check(got, expected Type) bool {
 | 
					pub fn (t &Table) check(got, expected Type) bool {
 | 
				
			||||||
	got_idx := type_idx(got)
 | 
						got_idx := got.idx()
 | 
				
			||||||
	exp_idx := type_idx(expected)
 | 
						exp_idx := expected.idx()
 | 
				
			||||||
	// got_is_ptr := type_is_ptr(got)
 | 
						// got_is_ptr := got.is_ptr()
 | 
				
			||||||
	exp_is_ptr := type_is_ptr(expected)
 | 
						exp_is_ptr := expected.is_ptr()
 | 
				
			||||||
	// println('check: $got_type_sym.name, $exp_type_sym.name')
 | 
						// println('check: $got_type_sym.name, $exp_type_sym.name')
 | 
				
			||||||
	// # NOTE: use idxs here, and symbols below for perf
 | 
						// # NOTE: use idxs here, and symbols below for perf
 | 
				
			||||||
	if got_idx == none_type_idx {
 | 
						if got_idx == none_type_idx {
 | 
				
			||||||
| 
						 | 
					@ -504,7 +504,7 @@ pub fn (t &Table) check(got, expected Type) bool {
 | 
				
			||||||
	// }
 | 
						// }
 | 
				
			||||||
	if got_type_sym.kind == .array_fixed && exp_type_sym.kind == .byteptr {
 | 
						if got_type_sym.kind == .array_fixed && exp_type_sym.kind == .byteptr {
 | 
				
			||||||
		info := got_type_sym.info as ArrayFixed
 | 
							info := got_type_sym.info as ArrayFixed
 | 
				
			||||||
		if type_idx(info.elem_type) == byte_type_idx {
 | 
							if info.elem_type.idx() == byte_type_idx {
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue