v: support `$for attr in Test.attributes` (#9836)
							parent
							
								
									515e83dcbc
								
							
						
					
					
						commit
						fc3b628440
					
				| 
						 | 
				
			
			@ -121,3 +121,18 @@ pub:
 | 
			
		|||
	is_mut bool
 | 
			
		||||
	typ    int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum AttributeKind {
 | 
			
		||||
	plain // [name]
 | 
			
		||||
	string // ['name']
 | 
			
		||||
	number // [123]
 | 
			
		||||
	comptime_define // [if name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct StructAttribute {
 | 
			
		||||
pub:
 | 
			
		||||
	name    string
 | 
			
		||||
	has_arg bool
 | 
			
		||||
	arg     string
 | 
			
		||||
	kind    AttributeKind
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -786,6 +786,7 @@ pub:
 | 
			
		|||
pub enum CompForKind {
 | 
			
		||||
	methods
 | 
			
		||||
	fields
 | 
			
		||||
	attributes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct CompFor {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -488,5 +488,6 @@ pub fn (e CompForKind) str() string {
 | 
			
		|||
	match e {
 | 
			
		||||
		.methods { return 'methods' }
 | 
			
		||||
		.fields { return 'fields' }
 | 
			
		||||
		.attributes { return 'attributes' }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -468,6 +468,22 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
 | 
			
		|||
			}
 | 
			
		||||
			g.comptime_var_type_map.delete(node.val_var)
 | 
			
		||||
		}
 | 
			
		||||
	} else if node.kind == .attributes {
 | 
			
		||||
		if sym.info is ast.Struct {
 | 
			
		||||
			if sym.info.attrs.len > 0 {
 | 
			
		||||
				g.writeln('\tStructAttribute $node.val_var = {0};')
 | 
			
		||||
			}
 | 
			
		||||
			for attr in sym.info.attrs {
 | 
			
		||||
				g.writeln('/* attribute $i */ {')
 | 
			
		||||
 | 
			
		||||
				g.writeln('\t${node.val_var}.name = _SLIT("$attr.name");')
 | 
			
		||||
				g.writeln('\t${node.val_var}.has_arg = $attr.has_arg;')
 | 
			
		||||
				g.writeln('\t${node.val_var}.arg = _SLIT("$attr.arg");')
 | 
			
		||||
				g.writeln('\t${node.val_var}.kind = AttributeKind_$attr.kind;')
 | 
			
		||||
 | 
			
		||||
				g.writeln('}')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	g.indent--
 | 
			
		||||
	g.writeln('}// \$for')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -253,8 +253,15 @@ fn (mut p Parser) comp_for() ast.CompFor {
 | 
			
		|||
			pos: var_pos
 | 
			
		||||
		})
 | 
			
		||||
		kind = .fields
 | 
			
		||||
	} else if for_val == 'attributes' {
 | 
			
		||||
		p.scope.register(ast.Var{
 | 
			
		||||
			name: val_var
 | 
			
		||||
			typ: p.table.find_type_idx('StructAttribute')
 | 
			
		||||
			pos: var_pos
 | 
			
		||||
		})
 | 
			
		||||
		kind = .attributes
 | 
			
		||||
	} else {
 | 
			
		||||
		p.error_with_pos('unknown kind `$for_val`, available are: `methods` or `fields`',
 | 
			
		||||
		p.error_with_pos('unknown kind `$for_val`, available are: `methods`, `fields` or `attributes`',
 | 
			
		||||
			p.prev_tok.position())
 | 
			
		||||
		return ast.CompFor{}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
[test: 'hello']
 | 
			
		||||
[abc]
 | 
			
		||||
struct Test {}
 | 
			
		||||
 | 
			
		||||
fn test_attributes() {
 | 
			
		||||
	$for attr in Test.attributes {
 | 
			
		||||
		if attr.has_arg {
 | 
			
		||||
			assert attr.name == 'test'
 | 
			
		||||
			assert attr.arg == 'hello'
 | 
			
		||||
		} else {
 | 
			
		||||
			assert attr.name == 'abc'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue