ast_result_t expr_ffi(pass_opt_t* opt, ast_t* ast) { if(!package_allow_ffi(&opt->check)) { ast_error(opt->check.errors, ast, "This package isn't allowed to do C FFI"); return AST_FATAL; } AST_GET_CHILDREN(ast, name, return_typeargs, args, namedargs, question); assert(name != NULL); ast_t* decl; if(!ffi_get_decl(&opt->check, ast, &decl, opt)) return AST_ERROR; if(decl != NULL) // We have a declaration return declared_ffi(opt, ast, decl); // We do not have a declaration for(ast_t* arg = ast_child(args); arg != NULL; arg = ast_sibling(arg)) { ast_t* a_type = ast_type(arg); if((a_type != NULL) && is_type_literal(a_type)) { ast_error(opt->check.errors, arg, "Cannot pass number literals as unchecked FFI arguments"); return AST_ERROR; } } ast_t* return_type = ast_child(return_typeargs); if(return_type == NULL) { ast_error(opt->check.errors, name, "FFIs without declarations must specify return type"); return AST_ERROR; } ast_settype(ast, return_type); ast_inheritflags(ast); if(ast_id(question) == TK_QUESTION) ast_seterror(ast); return AST_OK; }
bool expr_ffi(pass_opt_t* opt, ast_t* ast) { AST_GET_CHILDREN(ast, name, return_typeargs, args, namedargs, question); assert(name != NULL); ast_t* decl; if(!ffi_get_decl(&opt->check, ast, &decl, opt)) return false; if(decl != NULL) // We have a declaration return declared_ffi(opt, ast, decl); // We do not have a declaration for(ast_t* arg = ast_child(args); arg != NULL; arg = ast_sibling(arg)) { ast_t* a_type = ast_type(arg); if((a_type != NULL) && is_type_literal(a_type)) { ast_error(opt->check.errors, arg, "Cannot pass number literals as unchecked FFI arguments"); return false; } } ast_t* return_type = ast_child(return_typeargs); if(return_type == NULL) { ast_error(opt->check.errors, name, "FFIs without declarations must specify return type"); return false; } ast_settype(ast, return_type); return true; }