Skip to content

Commit ed55cb8

Browse files
committed
chore: merge main
2 parents aa4315d + 11ebdd5 commit ed55cb8

18 files changed

Lines changed: 4664 additions & 18 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Push every commit to `main` into `nightly-testing`
2+
3+
name: Push to Nightly
4+
5+
on:
6+
push:
7+
branches: ["main"]
8+
9+
jobs:
10+
push-to-nightly:
11+
runs-on: ubuntu-latest
12+
steps:
13+
14+
- name: checkout repo
15+
uses: actions/checkout@v6
16+
with:
17+
ref: nightly-testing
18+
fetch-depth: 0
19+
token: ${{ secrets.UNICODE_BASIC_TOKEN }}
20+
21+
- name: merge main
22+
run: |
23+
git config user.name "${{ github.actor }}"
24+
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
25+
git merge origin/main --no-commit --strategy-option ours --allow-unrelated-histories
26+
git restore --staged lean-toolchain lake-manifest.json
27+
git commit --allow-empty -m "chore: merge main into nightly-testing"
28+
git push origin nightly-testing

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
zip -rq docs-${TAG_NAME}.zip doc doc-data
3838
3939
- name: Release
40-
uses: softprops/action-gh-release@v2
40+
uses: softprops/action-gh-release@v3
4141
with:
4242
files: |
4343
docs/docs-${{ github.ref_name }}.tar.gz
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
name: Update Nightly Testing
1+
name: Update Nightly Toolchain
22

33
on:
4+
workflow_dispatch:
45
schedule:
56
- cron: '0 9 * * *'
6-
workflow_dispatch:
77

88
jobs:
99
update:
@@ -22,22 +22,20 @@ jobs:
2222
- name: set user
2323
run: |
2424
git config user.name "${{ github.actor }}"
25-
git config user.email "${{ github.actor_id}}+${{ github.actor }}@users.noreply.github.com"
26-
27-
- name: merge main
28-
run: |
29-
git fetch origin
30-
git merge origin/main --strategy-option theirs --no-commit --allow-unrelated-histories
25+
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
3126
32-
- name: update lean-toolchain
27+
- name: get toochain tags
3328
id: toolchain-tag
3429
run: |
3530
LEAN_TAG=$(curl -s "https://api.github.com/repos/leanprover/lean4-nightly/releases" | jq -r '.[0].tag_name')
31+
REPO_TAG=$(cut -d ':' -f2 lean-toolchain | tr -d '\n')
3632
echo "lean_tag=$LEAN_TAG" >> $GITHUB_OUTPUT
37-
echo "leanprover/lean4:$LEAN_TAG" > lean-toolchain
38-
git add lean-toolchain
33+
echo "repo_tag=$REPO_TAG" >> $GITHUB_OUTPUT
3934
4035
- name: commit and push
36+
if: ${{ steps.toolchain-tag.outputs.lean_tag != steps.toolchain-tag.outputs.repo_tag }}
4137
run: |
38+
echo "leanprover/lean4:${{ steps.toolchain-tag.outputs.lean_tag }}" > lean-toolchain
39+
git add lean-toolchain
4240
git commit -m "chore: update toolchain ${{ steps.toolchain-tag.outputs.lean_tag }}"
4341
git push origin nightly-testing

.github/workflows/update-toolchain.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
- name: checkout
1515
uses: actions/checkout@v6
1616
with:
17+
ref: nightly-testing
1718
fetch-depth: 0
1819

1920
- name: install jq
@@ -22,7 +23,7 @@ jobs:
2223
- name: get toolchain tags
2324
id: toolchain-tag
2425
run: |
25-
REPO_TAG=$(sed 's/.*://1' lean-toolchain | tr -d '\n')
26+
REPO_TAG=$(git show main:lean-toolchain | cut -d':' -f2 | tr -d '\n')
2627
LEAN_TAG=$(curl -s "https://api.github.com/repos/leanprover/lean4/releases" | jq -r '.[0].tag_name' | tr -d '\n')
2728
echo "repo_tag=$REPO_TAG" >> $GITHUB_OUTPUT
2829
echo "lean_tag=$LEAN_TAG" >> $GITHUB_OUTPUT
@@ -32,15 +33,16 @@ jobs:
3233
if: ${{ steps.toolchain-tag.outputs.lean_tag != steps.toolchain-tag.outputs.repo_tag }}
3334
run: |
3435
git config user.name "${{ github.actor }}"
35-
git config user.email "${{ github.actor_id}}+${{ github.actor }}@users.noreply.github.com"
36-
git merge -X theirs origin/nightly-testing
36+
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
3737
echo "leanprover/lean4:${{ steps.toolchain-tag.outputs.lean_tag }}" > lean-toolchain
3838
3939
- name: create pull request
40+
if: ${{ steps.toolchain-tag.outputs.lean_tag != steps.toolchain-tag.outputs.repo_tag }}
4041
uses: peter-evans/create-pull-request@v8
4142
with:
4243
token: ${{ secrets.UNICODE_BASIC_TOKEN }}
4344
commit-message: "chore: update toolchain ${{ steps.toolchain-tag.outputs.lean_tag }}"
4445
branch: update-toolchain-${{ steps.toolchain-tag.outputs.lean_tag }}
46+
base: main
4547
delete-branch: true
4648
title: "chore: update toolchain ${{ steps.toolchain-tag.outputs.lean_tag }}"

UnicodeBasic.lean

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace Unicode
5151
/-- Get character name
5252
5353
When the Unicode property `Name` is empty, a unique code label is returned
54-
as described in Unicode Standard, section 4.8. These labels start with
54+
as recommended in Unicode Standard, section 4.8. These labels start with
5555
`'<'` (U+003C) and end with `'>'` (U+003E) so they are distinguishable from
5656
actual name values.
5757
@@ -60,6 +60,27 @@ namespace Unicode
6060
@[inline]
6161
def getName (char : Char) : String := lookupName char.val
6262

63+
/-!
64+
## Script ##
65+
-/
66+
67+
/-- Get character script
68+
69+
Unicode property: `Script`
70+
-/
71+
@[inline]
72+
def getScript (char : Char) : Script := lookupScript char.val
73+
74+
/-- Get script name
75+
76+
Returns `none` if the script code is unassigned.
77+
78+
Unicode property: `Script`
79+
-/
80+
@[inline]
81+
def getScriptName? (s : Script) : Option String :=
82+
lookupScriptName s |>.map toString
83+
6384
/-!
6485
## Bidirectional Properties ##
6586
-/

UnicodeBasic/TableLookup.lean

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ protected abbrev oMath : UInt64 := 0x800000000
2323
@[extern "unicode_prop_lookup"]
2424
protected opaque lookupProp (c : UInt32) : UInt64
2525

26+
@[extern "unicode_script_lookup"]
27+
protected opaque lookupScript (c : UInt32) : Script
28+
2629
end CLib
2730

2831
/-- Binary search -/
@@ -387,4 +390,22 @@ where
387390
str : String := include_str "../data/table/White_Space.txt"
388391
table : Thunk <| Array (UInt32 × UInt32) := parsePropTable str
389392

393+
/-- Get the script of a code point using lookup table
394+
395+
Unicode property: `Script` -/
396+
@[inline]
397+
def lookupScript (c : UInt32) : Script := CLib.lookupScript c
398+
399+
/-- Get the name of a script
400+
401+
Unicode property: `Script` -/
402+
def lookupScriptName (s : Script) : Option String.Slice :=
403+
let table := table.get
404+
if s.code < table[0]!.1 then none else
405+
match table[find s.code (fun i => table[i]!.1) 0 table.size.toUSize]! with
406+
| (c, v) => if s.code = c then some v else none
407+
where
408+
str : String := include_str "../data/table/Script_Name.txt"
409+
table : Thunk <| Array (UInt32 × String.Slice) := parseTable str fun _ n => n[0]!
410+
390411
end Unicode

UnicodeBasic/Types.lean

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ Copyright © 2023-2025 François G. Dorais. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
-/
55
module
6+
public import Std.Data.HashMap
7+
68
public section
9+
710
/-- Low-level conversion from `UInt32` to `Char` (*unsafe*)
811
912
This function translates to a no-op in the compiler. However, it does not
@@ -1014,5 +1017,65 @@ def BidiClass.ofAbbrev! (abbr : String.Slice) : BidiClass :=
10141017
instance : Repr BidiClass where
10151018
reprPrec bc _ := s!"Unicode.BidiClass.{bc.toAbbrev}"
10161019

1020+
/-!
1021+
## Scripts ##
1022+
-/
1023+
1024+
/-- Check if valid script identifier -/
1025+
@[inline]
1026+
def Script.isValid (c : UInt32) : Bool :=
1027+
let c0 := (c >>> 24).toUInt8
1028+
let c1 := (c >>> 16).toUInt8
1029+
let c2 := (c >>> 8).toUInt8
1030+
let c3 := c.toUInt8
1031+
(c0 ≤ 'Z'.toUInt8 && 'A'.toUInt8 ≤ c0)
1032+
&& (c1 ≤ 'z'.toUInt8 && 'a'.toUInt8 ≤ c1)
1033+
&& (c2 ≤ 'z'.toUInt8 && 'a'.toUInt8 ≤ c2)
1034+
&& (c3 ≤ 'z'.toUInt8 && 'a'.toUInt8 ≤ c3)
1035+
1036+
/-- Script identifier type -/
1037+
structure Script where
1038+
code : UInt32
1039+
is_valid : Script.isValid code
1040+
deriving DecidableEq, Hashable
1041+
1042+
namespace Script
1043+
1044+
/-- Default value is `Zzzz` (`Unknown`) -/
1045+
instance : Inhabited Script where
1046+
default := {
1047+
code := (((('Z'.val <<< 8 ||| 'z'.val) <<< 8) ||| 'z'.val) <<< 8) ||| 'z'.val
1048+
is_valid := by decide
1049+
}
1050+
1051+
/-- String abbreviation of script -/
1052+
@[extern "unicode_script_to_abbrev"]
1053+
def toAbbrev : Script → String
1054+
| ⟨c, _⟩ =>
1055+
let c0 := Char.ofUInt8 (c >>> 24).toUInt8
1056+
let c1 := Char.ofUInt8 (c >>> 16).toUInt8
1057+
let c2 := Char.ofUInt8 (c >>> 8).toUInt8
1058+
let c3 := Char.ofUInt8 c.toUInt8
1059+
String.ofList [c0, c1, c2, c3]
1060+
1061+
@[extern "unicode_script_of_abbrev"]
1062+
private opaque ofAbbrevAux (abbr : String) : UInt32
1063+
1064+
/-- Get script from abbreviation -/
1065+
def ofAbbrev? (abbr : String.Slice) : Option Script :=
1066+
if abbr.utf8ByteSize = 4 then
1067+
let code := ofAbbrevAux abbr.toString
1068+
if h : Script.isValid code then
1069+
some ⟨code, h⟩
1070+
else
1071+
none
1072+
else
1073+
none
1074+
1075+
@[inline, inherit_doc ofAbbrev?]
1076+
def ofAbbrev! (abbr : String.Slice) : Script := ofAbbrev? abbr |>.get!
1077+
1078+
end Script
1079+
10171080
end Unicode
10181081
end

UnicodeCLib/basic.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include <lean/lean.h>
2+
#ifdef _WIN32
3+
#include <winsock2.h>
4+
#else
5+
#include <arpa/inet.h>
6+
#endif
7+
#include "basic.h"
8+
9+
static inline int unicode_script_is_valid(uint32_t c) {
10+
int c0 = (int)(c >> 24 & 0xff);
11+
int c1 = (int)(c >> 16 & 0xff);
12+
int c2 = (int)(c >> 8 & 0xff);
13+
int c3 = (int)(c & 0xff);
14+
return
15+
c0 <= 'Z' && 'A' <= c0 &&
16+
c1 <= 'z' && 'a' <= c1 &&
17+
c2 <= 'z' && 'a' <= c2 &&
18+
c3 <= 'z' && 'a' <= c3;
19+
}
20+
21+
uint32_t unicode_script_of_abbrev(b_lean_obj_arg abbr) {
22+
lean_string_object * str = lean_to_string(abbr);
23+
assert(str->m_size > 4);
24+
uint32_t val = *((uint32_t*)(str->m_data));
25+
return ntohl(val);
26+
}
27+
28+
lean_obj_res unicode_script_to_abbrev(uint32_t scr) {
29+
assert(unicode_script_is_valid(scr));
30+
lean_object * abbr = lean_alloc_string(5, 5, 4);
31+
lean_to_string(abbr)->m_data[4] = 0;
32+
*((uint32_t*)lean_to_string(abbr)->m_data) = htonl(scr);
33+
return abbr;
34+
}

UnicodeCLib/basic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ LEAN_EXPORT uint64_t unicode_prop_lookup(uint32_t c);
6969

7070
LEAN_EXPORT uint64_t unicode_case_lookup(uint32_t c);
7171

72+
LEAN_EXPORT uint32_t unicode_script_lookup(uint32_t c);
73+
74+
LEAN_EXPORT uint32_t unicode_script_of_abbrev(b_lean_obj_arg abbr);
75+
76+
LEAN_EXPORT lean_obj_res unicode_script_to_abbrev(uint32_t scr);
77+
7278
#ifdef __cplusplus
7379
}
7480
#endif

0 commit comments

Comments
 (0)