lean4-htt/src/Lean/Compiler/ExportAttr.lean
jrr6 fcbd1037fd
refactor: update and consolidate attribute-related error messages (#9495)
This PR consolidates common attribute-related error messages into
reusable functions and updates the wording and formatting of relevant
error messages.
2025-07-26 02:03:18 +00:00

73 lines
2.1 KiB
Text

/-
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Attributes
public section
namespace Lean
private def isValidCppId (id : String) : Bool :=
let first := id.get 0;
first.isAlpha && (id.toSubstring.drop 1).all (fun c => c.isAlpha || c.isDigit || c == '_')
private def isValidCppName : Name → Bool
| .str .anonymous s => isValidCppId s
| .str p s => isValidCppId s && isValidCppName p
| _ => false
/--
Exports a function under the provided unmangled symbol name. This can be used to refer to Lean
functions from other programming languages like C.
Example:
```
@[export lean_color_from_map]
def colorValue (properties : @& Std.HashMap String String) : UInt32 :=
match properties["color"]? with
| some "red" => 0xff0000
| some "green" => 0x00ff00
| some "blue" => 0x0000ff
| _ => -1
```
C code:
```c
#include <lean/lean.h>
uint32_t lean_color_from_map(b_lean_obj_arg properties);
void fill_rectangle_from_map(b_lean_obj_arg properties) {
uint32_t color = lean_color_from_map(properties);
// ...
}
```
The opposite of this is `@[extern]`, which allows Lean functions to refer to functions from other
programming languages.
-/
@[builtin_doc]
builtin_initialize exportAttr : ParametricAttribute Name ←
registerParametricAttribute {
name := `export,
descr := "name to be used by code generators",
getParam := fun _ stx => do
let exportName ← Attribute.Builtin.getId stx
unless isValidCppName exportName do
throwError "Invalid `export` function name: `{exportName}` is not a valid C++ identifier"
return exportName
}
def getExportNameFor? (env : Environment) (n : Name) : Option Name :=
exportAttr.getParam? env n
def isExport (env : Environment) (n : Name) : Bool :=
-- The main function morally is an exported function as well. In particular,
-- it should not participate in borrow inference.
(getExportNameFor? env n).isSome || n == `main
end Lean