all: add builtin channel type `chan elem_type` (#6126)
							parent
							
								
									75212f9fab
								
							
						
					
					
						commit
						9602a25a0b
					
				| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					import sync
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						num_iterations = 10000
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct St {
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
 | 
						n int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// this function gets an array of channels for `St` references
 | 
				
			||||||
 | 
					fn do_rec_calc_send(chs []chan mut St) {
 | 
				
			||||||
 | 
						mut s := St{}
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							if !(&sync.Channel(chs[0])).pop(&s) {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							s.n++
 | 
				
			||||||
 | 
							(&sync.Channel(chs[1])).push(&s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_channel_array_mut() {
 | 
				
			||||||
 | 
						mut chs := [chan mut St{cap: 1}, chan mut St{}]
 | 
				
			||||||
 | 
						go do_rec_calc_send(chs)
 | 
				
			||||||
 | 
						mut t := St{
 | 
				
			||||||
 | 
							n: 100
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _ in 0 .. num_iterations {
 | 
				
			||||||
 | 
							(&sync.Channel(chs[0])).push(&t)
 | 
				
			||||||
 | 
							(&sync.Channel(chs[1])).pop(&t)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						(&sync.Channel(chs[0])).close()
 | 
				
			||||||
 | 
						assert t.n == 100 + num_iterations
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,76 @@
 | 
				
			||||||
 | 
					import sync
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_rec_i64(ch chan i64) {
 | 
				
			||||||
 | 
						mut sum := i64(0)
 | 
				
			||||||
 | 
						for _ in 0 .. 300 {
 | 
				
			||||||
 | 
							mut a := i64(0)
 | 
				
			||||||
 | 
							(&sync.Channel(ch)).pop(&a)
 | 
				
			||||||
 | 
							sum += a
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						assert sum == 300 * (300 - 1) / 2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_send_int(ch chan int) {
 | 
				
			||||||
 | 
						for i in 0 .. 300 {
 | 
				
			||||||
 | 
							(&sync.Channel(ch)).push(&i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_send_byte(ch chan byte) {
 | 
				
			||||||
 | 
						for i in 0 .. 300 {
 | 
				
			||||||
 | 
							ii := byte(i)
 | 
				
			||||||
 | 
							(&sync.Channel(ch)).push(&ii)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_send_i64(mut ch sync.Channel) {
 | 
				
			||||||
 | 
						for i in 0 .. 300 {
 | 
				
			||||||
 | 
							ii := i64(i)
 | 
				
			||||||
 | 
							ch.push(&ii)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_select() {
 | 
				
			||||||
 | 
						chi := chan int{}
 | 
				
			||||||
 | 
						mut chl := sync.new_channel<i64>(1)
 | 
				
			||||||
 | 
						chb := chan byte{cap: 10}
 | 
				
			||||||
 | 
						recch := chan i64{cap: 0}
 | 
				
			||||||
 | 
						go do_rec_i64(recch)
 | 
				
			||||||
 | 
						go do_send_int(chi)
 | 
				
			||||||
 | 
						go do_send_byte(chb)
 | 
				
			||||||
 | 
						go do_send_i64(mut chl)
 | 
				
			||||||
 | 
						mut channels := [&sync.Channel(chi), &sync.Channel(recch), chl, &sync.Channel(chb)]
 | 
				
			||||||
 | 
						directions := [sync.Direction.pop, .push, .pop, .pop]
 | 
				
			||||||
 | 
						mut sum := i64(0)
 | 
				
			||||||
 | 
						mut rl := i64(0)
 | 
				
			||||||
 | 
						mut ri := int(0)
 | 
				
			||||||
 | 
						mut rb := byte(0)
 | 
				
			||||||
 | 
						mut sl := i64(0)
 | 
				
			||||||
 | 
						mut objs := [voidptr(&ri), &sl, &rl, &rb]
 | 
				
			||||||
 | 
						for _ in 0 .. 1200 {
 | 
				
			||||||
 | 
							idx := sync.channel_select(mut channels, directions, mut objs, -1)
 | 
				
			||||||
 | 
							match idx {
 | 
				
			||||||
 | 
								0 {
 | 
				
			||||||
 | 
									sum += ri
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								1 {
 | 
				
			||||||
 | 
									sl++
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								2 {
 | 
				
			||||||
 | 
									sum += rl
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								3 {
 | 
				
			||||||
 | 
									sum += rb
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									println('got $idx (timeout)')
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Use Gauß' formula for the first 2 contributions
 | 
				
			||||||
 | 
						expected_sum :=  2 * (300 * (300 - 1) / 2) +
 | 
				
			||||||
 | 
							// the 3rd contribution is `byte` and must be seen modulo 256
 | 
				
			||||||
 | 
							256 * (256 - 1) / 2 +
 | 
				
			||||||
 | 
							44 * (44 - 1) / 2
 | 
				
			||||||
 | 
						assert sum == expected_sum
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -111,6 +111,10 @@ pub:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn new_channel<T>(n u32) &Channel {
 | 
					pub fn new_channel<T>(n u32) &Channel {
 | 
				
			||||||
	st := sizeof(T)
 | 
						st := sizeof(T)
 | 
				
			||||||
 | 
						return new_channel_st(n, st)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn new_channel_st(n u32, st u32) &Channel {
 | 
				
			||||||
	return &Channel{
 | 
						return &Channel{
 | 
				
			||||||
		writesem: new_semaphore_init(if n > 0 { n + 1 } else { 1 })
 | 
							writesem: new_semaphore_init(if n > 0 { n + 1 } else { 1 })
 | 
				
			||||||
		readsem:  new_semaphore_init(if n > 0 { u32(0) } else { 1 })
 | 
							readsem:  new_semaphore_init(if n > 0 { u32(0) } else { 1 })
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ import v.errors
 | 
				
			||||||
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
 | 
					pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr |
 | 
					pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr |
 | 
				
			||||||
	CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr |
 | 
						CharLiteral | ChanInit | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr |
 | 
				
			||||||
	IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr |
 | 
						IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr |
 | 
				
			||||||
	None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf |
 | 
						None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf |
 | 
				
			||||||
	SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
 | 
						SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
 | 
				
			||||||
| 
						 | 
					@ -751,6 +751,16 @@ pub mut:
 | 
				
			||||||
	typ             table.Type
 | 
						typ             table.Type
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct ChanInit {
 | 
				
			||||||
 | 
					pub:
 | 
				
			||||||
 | 
						pos        token.Position
 | 
				
			||||||
 | 
						cap_expr   Expr
 | 
				
			||||||
 | 
						has_cap    bool
 | 
				
			||||||
 | 
					pub mut:
 | 
				
			||||||
 | 
						typ        table.Type
 | 
				
			||||||
 | 
						elem_type  table.Type
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct MapInit {
 | 
					pub struct MapInit {
 | 
				
			||||||
pub:
 | 
					pub:
 | 
				
			||||||
	pos        token.Position
 | 
						pos        token.Position
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2345,6 +2345,9 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
 | 
				
			||||||
		ast.CallExpr {
 | 
							ast.CallExpr {
 | 
				
			||||||
			return c.call_expr(mut node)
 | 
								return c.call_expr(mut node)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							ast.ChanInit {
 | 
				
			||||||
 | 
								return c.chan_init(mut node)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ast.CharLiteral {
 | 
							ast.CharLiteral {
 | 
				
			||||||
			return table.byte_type
 | 
								return table.byte_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3198,6 +3201,17 @@ pub fn (mut c Checker) enum_val(mut node ast.EnumVal) table.Type {
 | 
				
			||||||
	return typ
 | 
						return typ
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (mut c Checker) chan_init(mut node ast.ChanInit) table.Type {
 | 
				
			||||||
 | 
						if node.typ != 0 {
 | 
				
			||||||
 | 
							info := c.table.get_type_symbol(node.typ).chan_info()
 | 
				
			||||||
 | 
							node.elem_type = info.elem_type
 | 
				
			||||||
 | 
							return node.typ
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							c.error('`chan` of unknown type', node.pos)
 | 
				
			||||||
 | 
							return node.typ
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut c Checker) map_init(mut node ast.MapInit) table.Type {
 | 
					pub fn (mut c Checker) map_init(mut node ast.MapInit) table.Type {
 | 
				
			||||||
	// `x ;= map[string]string` - set in parser
 | 
						// `x ;= map[string]string` - set in parser
 | 
				
			||||||
	if node.typ != 0 {
 | 
						if node.typ != 0 {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -799,6 +799,16 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
 | 
				
			||||||
		ast.CallExpr {
 | 
							ast.CallExpr {
 | 
				
			||||||
			f.call_expr(node)
 | 
								f.call_expr(node)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							ast.ChanInit {
 | 
				
			||||||
 | 
								f.write('chan[')
 | 
				
			||||||
 | 
								f.write(f.type_to_str(node.elem_type))
 | 
				
			||||||
 | 
								f.write(']{')
 | 
				
			||||||
 | 
								if node.has_cap {
 | 
				
			||||||
 | 
									f.write('cap: ')
 | 
				
			||||||
 | 
									f.expr(node.cap_expr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								f.write('}')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ast.CharLiteral {
 | 
							ast.CharLiteral {
 | 
				
			||||||
			f.write('`$node.val`')
 | 
								f.write('`$node.val`')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -497,6 +497,10 @@ typedef struct {
 | 
				
			||||||
			.interface_ {
 | 
								.interface_ {
 | 
				
			||||||
				g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
 | 
									g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								.chan {
 | 
				
			||||||
 | 
									styp := util.no_dots(typ.name)
 | 
				
			||||||
 | 
									g.type_definitions.writeln('typedef chan $styp;')
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			.map {
 | 
								.map {
 | 
				
			||||||
				styp := util.no_dots(typ.name)
 | 
									styp := util.no_dots(typ.name)
 | 
				
			||||||
				g.type_definitions.writeln('typedef map $styp;')
 | 
									g.type_definitions.writeln('typedef map $styp;')
 | 
				
			||||||
| 
						 | 
					@ -1787,6 +1791,18 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
				
			||||||
				g.write('))')
 | 
									g.write('))')
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							ast.ChanInit {
 | 
				
			||||||
 | 
								elem_typ_str := g.typ(node.elem_type)
 | 
				
			||||||
 | 
								g.write('sync__new_channel_st(')
 | 
				
			||||||
 | 
								if node.has_cap {
 | 
				
			||||||
 | 
									g.expr(node.cap_expr)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									g.write('0')
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								g.write(', sizeof(')
 | 
				
			||||||
 | 
								g.write(elem_typ_str)
 | 
				
			||||||
 | 
								g.write('))')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ast.CharLiteral {
 | 
							ast.CharLiteral {
 | 
				
			||||||
			g.write("'$node.val'")
 | 
								g.write("'$node.val'")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,6 +415,8 @@ typedef map map_string;
 | 
				
			||||||
typedef byte array_fixed_byte_300 [300];
 | 
					typedef byte array_fixed_byte_300 [300];
 | 
				
			||||||
typedef byte array_fixed_byte_400 [400];
 | 
					typedef byte array_fixed_byte_400 [400];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct sync__Channel* chan;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef __cplusplus
 | 
					#ifndef __cplusplus
 | 
				
			||||||
	#ifndef bool
 | 
						#ifndef bool
 | 
				
			||||||
		typedef int bool;
 | 
							typedef int bool;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,6 +232,9 @@ pub fn (mut g JsGen) typ(t table.Type) string {
 | 
				
			||||||
			info := sym.info as table.ArrayFixed
 | 
								info := sym.info as table.ArrayFixed
 | 
				
			||||||
			styp = g.typ(info.elem_type) + '[]'
 | 
								styp = g.typ(info.elem_type) + '[]'
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							.chan {
 | 
				
			||||||
 | 
								styp = 'chan'
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		// 'map[string]int' => 'Map<string, number>'
 | 
							// 'map[string]int' => 'Map<string, number>'
 | 
				
			||||||
		.map {
 | 
							.map {
 | 
				
			||||||
			info := sym.info as table.Map
 | 
								info := sym.info as table.Map
 | 
				
			||||||
| 
						 | 
					@ -533,6 +536,9 @@ fn (mut g JsGen) expr(node ast.Expr) {
 | 
				
			||||||
		ast.CallExpr {
 | 
							ast.CallExpr {
 | 
				
			||||||
			g.gen_call_expr(node)
 | 
								g.gen_call_expr(node)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							ast.ChanInit {
 | 
				
			||||||
 | 
								// TODO
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ast.CastExpr {
 | 
							ast.CastExpr {
 | 
				
			||||||
			// JS has no types, so no need to cast
 | 
								// JS has no types, so no need to cast
 | 
				
			||||||
			// Just write the expression inside
 | 
								// Just write the expression inside
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,13 @@ pub fn (mut p Parser) parse_map_type() table.Type {
 | 
				
			||||||
	return table.new_type(idx)
 | 
						return table.new_type(idx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (mut p Parser) parse_chan_type() table.Type {
 | 
				
			||||||
 | 
						p.next()
 | 
				
			||||||
 | 
						elem_type := p.parse_type()
 | 
				
			||||||
 | 
						idx := p.table.find_or_register_chan(elem_type)
 | 
				
			||||||
 | 
						return table.new_type(idx)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut p Parser) parse_multi_return_type() table.Type {
 | 
					pub fn (mut p Parser) parse_multi_return_type() table.Type {
 | 
				
			||||||
	p.check(.lpar)
 | 
						p.check(.lpar)
 | 
				
			||||||
	mut mr_types := []table.Type{}
 | 
						mut mr_types := []table.Type{}
 | 
				
			||||||
| 
						 | 
					@ -211,6 +218,9 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr, check_dot
 | 
				
			||||||
			if name == 'map' {
 | 
								if name == 'map' {
 | 
				
			||||||
				return p.parse_map_type()
 | 
									return p.parse_map_type()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if name == 'chan' {
 | 
				
			||||||
 | 
									return p.parse_chan_type()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			defer {
 | 
								defer {
 | 
				
			||||||
				p.next()
 | 
									p.next()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -958,6 +958,47 @@ pub fn (mut p Parser) name_expr() ast.Expr {
 | 
				
			||||||
			typ: map_type
 | 
								typ: map_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// `chan typ{...}`
 | 
				
			||||||
 | 
						if p.tok.lit == 'chan' {
 | 
				
			||||||
 | 
							first_pos := p.tok.position()
 | 
				
			||||||
 | 
							mut last_pos := p.tok.position()
 | 
				
			||||||
 | 
							chan_type := p.parse_chan_type()
 | 
				
			||||||
 | 
							mut has_cap := false
 | 
				
			||||||
 | 
							mut cap_expr := ast.Expr{}
 | 
				
			||||||
 | 
							p.check(.lcbr)
 | 
				
			||||||
 | 
							if p.tok.kind == .rcbr {
 | 
				
			||||||
 | 
								last_pos = p.tok.position()
 | 
				
			||||||
 | 
								p.next()
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								key := p.check_name()
 | 
				
			||||||
 | 
								p.check(.colon)
 | 
				
			||||||
 | 
								match key {
 | 
				
			||||||
 | 
									'cap' {
 | 
				
			||||||
 | 
										has_cap = true
 | 
				
			||||||
 | 
										cap_expr = p.expr(0)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									'len', 'init' {
 | 
				
			||||||
 | 
										p.error('`$key` cannot be initialized for `chan`. Did you mean `cap`?')
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										p.error('wrong field `$key`, expecting `cap`')
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								last_pos = p.tok.position()
 | 
				
			||||||
 | 
								p.check(.rcbr)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pos := token.Position{
 | 
				
			||||||
 | 
								line_nr: first_pos.line_nr
 | 
				
			||||||
 | 
								pos: first_pos.pos
 | 
				
			||||||
 | 
								len: last_pos.pos - first_pos.pos + last_pos.len
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return ast.ChanInit{
 | 
				
			||||||
 | 
								pos: pos
 | 
				
			||||||
 | 
								has_cap: has_cap
 | 
				
			||||||
 | 
								cap_expr: cap_expr
 | 
				
			||||||
 | 
								typ: chan_type
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// Raw string (`s := r'hello \n ')
 | 
						// Raw string (`s := r'hello \n ')
 | 
				
			||||||
	if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && !p.inside_str_interp {
 | 
						if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && !p.inside_str_interp {
 | 
				
			||||||
		return p.string_expr()
 | 
							return p.string_expr()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ import strings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type Type int
 | 
					pub type Type int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type TypeInfo = Alias | Array | ArrayFixed | Enum | FnType | GenericStructInst | Interface |
 | 
					pub type TypeInfo = Alias | Array | ArrayFixed | Chan | Enum | FnType | GenericStructInst | Interface |
 | 
				
			||||||
	Map | MultiReturn | Struct | SumType
 | 
						Map | MultiReturn | Struct | SumType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum Language {
 | 
					pub enum Language {
 | 
				
			||||||
| 
						 | 
					@ -253,10 +253,11 @@ pub const (
 | 
				
			||||||
	ustring_type_idx = 19
 | 
						ustring_type_idx = 19
 | 
				
			||||||
	array_type_idx   = 20
 | 
						array_type_idx   = 20
 | 
				
			||||||
	map_type_idx     = 21
 | 
						map_type_idx     = 21
 | 
				
			||||||
	any_type_idx     = 22
 | 
						chan_type_idx    = 22
 | 
				
			||||||
 | 
						any_type_idx     = 23
 | 
				
			||||||
	// t_type_idx       = 23
 | 
						// t_type_idx       = 23
 | 
				
			||||||
	any_flt_type_idx = 23
 | 
						any_flt_type_idx = 24
 | 
				
			||||||
	any_int_type_idx = 24
 | 
						any_int_type_idx = 25
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const (
 | 
					pub const (
 | 
				
			||||||
| 
						 | 
					@ -293,6 +294,7 @@ pub const (
 | 
				
			||||||
	ustring_type = new_type(ustring_type_idx)
 | 
						ustring_type = new_type(ustring_type_idx)
 | 
				
			||||||
	array_type   = new_type(array_type_idx)
 | 
						array_type   = new_type(array_type_idx)
 | 
				
			||||||
	map_type     = new_type(map_type_idx)
 | 
						map_type     = new_type(map_type_idx)
 | 
				
			||||||
 | 
						chan_type    = new_type(chan_type_idx)
 | 
				
			||||||
	any_type     = new_type(any_type_idx)
 | 
						any_type     = new_type(any_type_idx)
 | 
				
			||||||
	// t_type       = new_type(t_type_idx)
 | 
						// t_type       = new_type(t_type_idx)
 | 
				
			||||||
	any_flt_type = new_type(any_flt_type_idx)
 | 
						any_flt_type = new_type(any_flt_type_idx)
 | 
				
			||||||
| 
						 | 
					@ -302,7 +304,7 @@ pub const (
 | 
				
			||||||
pub const (
 | 
					pub const (
 | 
				
			||||||
	builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16',
 | 
						builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16',
 | 
				
			||||||
		'u32', 'u64', 'any_int', 'f32', 'f64', 'any_float', 'string', 'ustring', 'char', 'byte', 'bool',
 | 
							'u32', 'u64', 'any_int', 'f32', 'f64', 'any_float', 'string', 'ustring', 'char', 'byte', 'bool',
 | 
				
			||||||
		'none', 'array', 'array_fixed', 'map', 'any', 'struct', 'mapnode', 'size_t']
 | 
							'none', 'array', 'array_fixed', 'map', 'chan', 'any', 'struct', 'mapnode', 'size_t']
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct MultiReturn {
 | 
					pub struct MultiReturn {
 | 
				
			||||||
| 
						 | 
					@ -342,6 +344,7 @@ pub enum Kind {
 | 
				
			||||||
	array
 | 
						array
 | 
				
			||||||
	array_fixed
 | 
						array_fixed
 | 
				
			||||||
	map
 | 
						map
 | 
				
			||||||
 | 
						chan
 | 
				
			||||||
	any
 | 
						any
 | 
				
			||||||
	struct_
 | 
						struct_
 | 
				
			||||||
	generic_struct_inst
 | 
						generic_struct_inst
 | 
				
			||||||
| 
						 | 
					@ -391,6 +394,14 @@ pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[inline]
 | 
				
			||||||
 | 
					pub fn (t &TypeSymbol) chan_info() Chan {
 | 
				
			||||||
 | 
						match t.info {
 | 
				
			||||||
 | 
							Chan { return *it }
 | 
				
			||||||
 | 
							else { panic('TypeSymbol.chan_info(): no chan info for type: $t.name') }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
pub fn (t &TypeSymbol) map_info() Map {
 | 
					pub fn (t &TypeSymbol) map_info() Map {
 | 
				
			||||||
	match t.info {
 | 
						match t.info {
 | 
				
			||||||
| 
						 | 
					@ -524,6 +535,11 @@ pub fn (mut t Table) register_builtin_type_symbols() {
 | 
				
			||||||
		name: 'map'
 | 
							name: 'map'
 | 
				
			||||||
		mod: 'builtin'
 | 
							mod: 'builtin'
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						t.register_type_symbol({
 | 
				
			||||||
 | 
							kind: .chan
 | 
				
			||||||
 | 
							name: 'chan'
 | 
				
			||||||
 | 
							mod: 'builtin'
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	t.register_type_symbol({
 | 
						t.register_type_symbol({
 | 
				
			||||||
		kind: .any
 | 
							kind: .any
 | 
				
			||||||
		name: 'any'
 | 
							name: 'any'
 | 
				
			||||||
| 
						 | 
					@ -616,6 +632,7 @@ pub fn (k Kind) str() string {
 | 
				
			||||||
		.array { 'array' }
 | 
							.array { 'array' }
 | 
				
			||||||
		.array_fixed { 'array_fixed' }
 | 
							.array_fixed { 'array_fixed' }
 | 
				
			||||||
		.map { 'map' }
 | 
							.map { 'map' }
 | 
				
			||||||
 | 
							.chan { 'chan' }
 | 
				
			||||||
		.multi_return { 'multi_return' }
 | 
							.multi_return { 'multi_return' }
 | 
				
			||||||
		.sum_type { 'sum_type' }
 | 
							.sum_type { 'sum_type' }
 | 
				
			||||||
		.alias { 'alias' }
 | 
							.alias { 'alias' }
 | 
				
			||||||
| 
						 | 
					@ -708,6 +725,11 @@ pub mut:
 | 
				
			||||||
	elem_type Type
 | 
						elem_type Type
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Chan {
 | 
				
			||||||
 | 
					pub mut:
 | 
				
			||||||
 | 
						elem_type   Type
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Map {
 | 
					pub struct Map {
 | 
				
			||||||
pub mut:
 | 
					pub mut:
 | 
				
			||||||
	key_type   Type
 | 
						key_type   Type
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,6 +320,13 @@ pub fn (t &Table) array_fixed_name(elem_type Type, size, nr_dims int) string {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[inline]
 | 
				
			||||||
 | 
					pub fn (t &Table) chan_name(elem_type Type) string {
 | 
				
			||||||
 | 
						elem_type_sym := t.get_type_symbol(elem_type)
 | 
				
			||||||
 | 
						suffix := if elem_type.is_ptr() { '_ptr' } else { '' }
 | 
				
			||||||
 | 
						return 'chan_$elem_type_sym.name' + suffix
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[inline]
 | 
					[inline]
 | 
				
			||||||
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)
 | 
				
			||||||
| 
						 | 
					@ -329,6 +336,25 @@ pub fn (t &Table) map_name(key_type, value_type Type) string {
 | 
				
			||||||
	// return 'map_${value_type_sym.name}' + suffix
 | 
						// return 'map_${value_type_sym.name}' + suffix
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (mut t Table) find_or_register_chan(elem_type Type) int {
 | 
				
			||||||
 | 
						name := t.chan_name(elem_type)
 | 
				
			||||||
 | 
						// existing
 | 
				
			||||||
 | 
						existing_idx := t.type_idxs[name]
 | 
				
			||||||
 | 
						if existing_idx > 0 {
 | 
				
			||||||
 | 
							return existing_idx
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// register
 | 
				
			||||||
 | 
						chan_typ := TypeSymbol{
 | 
				
			||||||
 | 
							parent_idx: chan_type_idx
 | 
				
			||||||
 | 
							kind: .chan
 | 
				
			||||||
 | 
							name: name
 | 
				
			||||||
 | 
							info: Chan{
 | 
				
			||||||
 | 
								elem_type: elem_type
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return t.register_type_symbol(chan_typ)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut t Table) find_or_register_map(key_type, value_type Type) int {
 | 
					pub fn (mut t Table) find_or_register_map(key_type, value_type Type) int {
 | 
				
			||||||
	name := t.map_name(key_type, value_type)
 | 
						name := t.map_name(key_type, value_type)
 | 
				
			||||||
	// existing
 | 
						// existing
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue