compiler: add support for `[if myflag]` void fn/methods
							parent
							
								
									945f964c0c
								
							
						
					
					
						commit
						9a19531909
					
				|  | @ -211,6 +211,7 @@ pub: | |||
| 	is_js         bool | ||||
| 	no_body       bool // just a definition `fn C.malloc()`
 | ||||
| 	is_builtin    bool // this function is defined in builtin/strconv
 | ||||
| 	ctdefine      string // has [if myflag] tag
 | ||||
| 	pos           token.Position | ||||
| } | ||||
| 
 | ||||
|  | @ -235,6 +236,7 @@ mut: | |||
| 	left_type          table.Type // type of `user`
 | ||||
| 	receiver_type      table.Type // User
 | ||||
| 	return_type        table.Type | ||||
| 	should_be_skipped  bool | ||||
| } | ||||
| 
 | ||||
| pub struct CallArg { | ||||
|  |  | |||
|  | @ -120,6 +120,11 @@ fn (c mut Checker) check_file_in_main(file ast.File) bool { | |||
| 						c.warn('function `$it.name` $no_pub_in_main_warning', it.pos) | ||||
| 					} | ||||
| 				} | ||||
| 				if it.ctdefine.len > 0 { | ||||
| 					if it.return_type != table.void_type { | ||||
| 						c.error('only functions that do NOT return values can have `[if ${it.ctdefine}]` tags', it.pos) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			ast.StructDecl { | ||||
| 				if it.is_pub { | ||||
|  | @ -497,6 +502,9 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type { | |||
| 			//println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
 | ||||
| 			c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos) | ||||
| 		} | ||||
| 		if method.return_type == table.void_type && method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines { | ||||
| 			call_expr.should_be_skipped = true | ||||
| 		} | ||||
| 		nr_args := if method.args.len == 0 {  0 } else {method.args.len - 1} | ||||
| 		min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 } | ||||
| 		if call_expr.args.len < min_required_args { | ||||
|  | @ -612,6 +620,11 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type { | |||
| 		return table.void_type | ||||
| 	} | ||||
| 	call_expr.return_type = f.return_type | ||||
| 
 | ||||
| 	if f.return_type == table.void_type && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines { | ||||
| 		call_expr.should_be_skipped = true | ||||
| 	} | ||||
| 
 | ||||
| 	if f.is_c || call_expr.is_c || f.is_js || call_expr.is_js { | ||||
| 		for arg in call_expr.args { | ||||
| 			c.expr(arg.expr) | ||||
|  |  | |||
|  | @ -224,6 +224,9 @@ fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) { | |||
| } | ||||
| 
 | ||||
| fn (mut g Gen) call_expr(node ast.CallExpr) { | ||||
| 	if node.should_be_skipped { | ||||
| 		return | ||||
| 	} | ||||
| 	gen_or := !g.is_assign_rhs && node.or_block.stmts.len > 0 | ||||
| 	tmp_opt := if gen_or { g.new_tmp_var() } else { '' } | ||||
| 	if gen_or { | ||||
|  |  | |||
|  | @ -170,6 +170,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 		end_pos = p.tok.position() | ||||
| 		return_type = p.parse_type() | ||||
| 	} | ||||
| 	ctdefine := p.attr_ctdefine | ||||
| 	// Register
 | ||||
| 	if is_method { | ||||
| 		mut type_sym := p.table.get_type_symbol(rec_type) | ||||
|  | @ -181,6 +182,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 			is_variadic: is_variadic | ||||
| 			is_generic: is_generic | ||||
| 			is_pub: is_pub | ||||
| 			ctdefine: ctdefine | ||||
| 		}) | ||||
| 	} else { | ||||
| 		if is_c { | ||||
|  | @ -202,6 +204,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 			is_js: is_js | ||||
| 			is_generic: is_generic | ||||
| 			is_pub: is_pub | ||||
| 			ctdefine: ctdefine | ||||
| 		}) | ||||
| 	} | ||||
| 	// Body
 | ||||
|  | @ -212,6 +215,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 	} | ||||
| 	p.close_scope() | ||||
| 	p.attr = '' | ||||
| 	p.attr_ctdefine = '' | ||||
| 	return ast.FnDecl{ | ||||
| 		name: name | ||||
| 		stmts: stmts | ||||
|  | @ -231,6 +235,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 		no_body: no_body | ||||
| 		pos: start_pos.extend(end_pos) | ||||
| 		is_builtin: p.builtin_mod || p.mod in util.builtin_module_parts | ||||
| 		ctdefine: ctdefine | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ mut: | |||
| 	builtin_mod       bool // are we in the `builtin` module?
 | ||||
| 	mod               string // current module name
 | ||||
| 	attr              string | ||||
| 	attr_ctdefine     string | ||||
| 	expr_mod          string | ||||
| 	scope             &ast.Scope | ||||
| 	global_scope      &ast.Scope | ||||
|  | @ -490,8 +491,10 @@ pub fn (mut p Parser) stmt() ast.Stmt { | |||
| 
 | ||||
| fn (mut p Parser) attribute() ast.Attr { | ||||
| 	p.check(.lsbr) | ||||
| 	mut is_if_attr := false | ||||
| 	if p.tok.kind == .key_if { | ||||
| 		p.next() | ||||
| 		is_if_attr = true | ||||
| 	} | ||||
| 	mut name := p.check_name() | ||||
| 	if p.tok.kind == .colon { | ||||
|  | @ -505,6 +508,9 @@ fn (mut p Parser) attribute() ast.Attr { | |||
| 	} | ||||
| 	p.check(.rsbr) | ||||
| 	p.attr = name | ||||
| 	if is_if_attr { | ||||
| 		p.attr_ctdefine = name | ||||
| 	} | ||||
| 	return ast.Attr{ | ||||
| 		name: name | ||||
| 	} | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ pub: | |||
| 	is_generic  bool | ||||
| 	is_pub      bool | ||||
| 	mod         string | ||||
| 	ctdefine    string // compile time define. myflag, when [if myflag] tag
 | ||||
| } | ||||
| 
 | ||||
| pub struct Arg { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue