This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git

commit c5318149784d0b1283d69438196fae4f4ba95f6b
Author: chaokunyang <[email protected]>
AuthorDate: Fri May 15 11:18:15 2026 +0000

    🔄 synced local 'docs/compiler/' with remote 'docs/compiler/'
---
 docs/compiler/compiler-guide.md |  25 +++++++++
 docs/compiler/generated-code.md | 115 ++++++++++++++++++++++++++++++++++++++++
 docs/compiler/index.md          |  15 +++---
 docs/compiler/schema-idl.md     |  41 ++++++++------
 4 files changed, 172 insertions(+), 24 deletions(-)

diff --git a/docs/compiler/compiler-guide.md b/docs/compiler/compiler-guide.md
index 28ed04f1f1..a1c35e0268 100644
--- a/docs/compiler/compiler-guide.md
+++ b/docs/compiler/compiler-guide.md
@@ -67,6 +67,7 @@ Compile options:
 | `--javascript_out=DST_DIR`            | Generate JavaScript code in DST_DIR  
                 | (none)        |
 | `--swift_out=DST_DIR`                 | Generate Swift code in DST_DIR       
                 | (none)        |
 | `--dart_out=DST_DIR`                  | Generate Dart code in DST_DIR        
                 | (none)        |
+| `--scala_out=DST_DIR`                 | Generate Scala 3 code in DST_DIR     
                 | (none)        |
 | `--go_nested_type_style`              | Go nested type naming: `camelcase` 
or `underscore`    | `underscore`  |
 | `--swift_namespace_style`             | Swift namespace style: `enum` or 
`flatten`            | `enum`        |
 | `--emit-fdl`                          | Emit translated FDL (for non-FDL 
inputs)              | `false`       |
@@ -174,6 +175,9 @@ foryc schema.fdl --java_out=./java/gen 
--python_out=./python/src --go_out=./go/g
 
 # Combine with import paths
 foryc schema.fdl --java_out=./gen/java -I proto/ -I common/
+
+# Generate Scala 3 code to a specific directory
+foryc schema.fdl --scala_out=./src/main/scala
 ```
 
 When using `--{lang}_out` options:
@@ -250,6 +254,7 @@ Compiling src/main.fdl...
 | JavaScript | `javascript` | `.ts`            | Interfaces with registration 
function  |
 | Swift      | `swift`      | `.swift`         | Fory Swift model macros       
         |
 | Dart       | `dart`       | `.dart`          | `@ForyStruct` classes with 
annotations |
+| Scala      | `scala`      | `.scala`         | Scala 3 models with macro 
derivation   |
 
 ## Output Structure
 
@@ -379,6 +384,26 @@ generated/
 - Registration helper class included in the part file
 - Typed arrays used for non-optional, non-ref primitive lists (e.g., 
`Int32List`)
 
+### Scala
+
+```
+generated/
+└── scala/
+    └── example/
+        ├── User.scala
+        ├── Status.scala
+        ├── Animal.scala
+        └── ExampleForyRegistration.scala
+```
+
+- One Scala 3 source file per generated type
+- Package structure matches the Fory IDL package
+- Messages derive `org.apache.fory.scala.ForySerializer`
+- `optional T` fields use `Option[T]`
+- Enums use Scala 3 `enum`
+- Unions use Scala 3 ADT `enum` with `@ForyUnion`, `@ForyCase`, and an 
`UnknownCase`
+- Registration helper object included
+
 ### C# IDL Matrix Verification
 
 Run the end-to-end C# IDL matrix (FDL/IDL/Proto/FBS generation plus roundtrip 
tests):
diff --git a/docs/compiler/generated-code.md b/docs/compiler/generated-code.md
index e3a8f9b7eb..723a4eb4cf 100644
--- a/docs/compiler/generated-code.md
+++ b/docs/compiler/generated-code.md
@@ -1042,6 +1042,121 @@ void main() {
 }
 ```
 
+## Scala
+
+The Scala target emits Scala 3 source only. The `fory-scala` runtime artifact
+still supports Scala 2.13 and Scala 3, but generated IDL source and macro
+derivation require Scala 3.
+
+### Output Layout
+
+For `package addressbook`, Scala output is generated under:
+
+- `<scala_out>/addressbook/`
+- Type files: `AddressBook.scala`, `Person.scala`, `Dog.scala`, `Cat.scala`, 
`Animal.scala`
+- Registration helper: `AddressbookForyRegistration.scala`
+
+### Type Generation
+
+Messages outside compiler-detected construction cycles generate case classes:
+
+```scala
+import org.apache.fory.annotation.{ForyField, ForyStruct}
+import org.apache.fory.scala.ForySerializer
+
+@ForyStruct
+final case class Person(
+  @ForyField(id = 1) name: String,
+  @ForyField(id = 3) email: Option[String],
+  @ForyField(id = 7) phones: List[Person.PhoneNumber],
+  @ForyField(id = 8) pet: Animal
+) derives ForySerializer
+```
+
+Messages in circular construction cycles generate normal classes with mutable
+serialized fields so reads can register the object before reading 
back-references:
+
+```scala
+import org.apache.fory.annotation.{ForyField, ForyStruct, Ref}
+import org.apache.fory.scala.ForySerializer
+
+@ForyStruct
+final class Node() derives ForySerializer {
+  @ForyField(id = 1)
+  var id: String = ""
+
+  @Ref
+  @ForyField(id = 2)
+  var parent: Option[Node @Ref] = None
+}
+```
+
+Enums generate Scala 3 enums with stable Fory IDs:
+
+```scala
+import org.apache.fory.annotation.ForyEnumId
+
+enum PhoneType {
+  @ForyEnumId(0)
+  case Mobile
+
+  @ForyEnumId(1)
+  case Home
+
+  @ForyEnumId(2)
+  case Work
+}
+```
+
+Unions generate Scala 3 ADT enums. Case ID `0` is reserved for the unknown-case
+carrier; schema-defined cases start at `1`.
+
+```scala
+import org.apache.fory.annotation.{ForyCase, ForyUnion}
+import org.apache.fory.scala.ForySerializer
+
+@ForyUnion
+enum Animal derives ForySerializer {
+  @ForyCase(id = 0)
+  case UnknownCase(caseId: Int, value: Any)
+
+  @ForyCase(id = 1)
+  case DogCase(value: Dog)
+
+  @ForyCase(id = 2)
+  case CatCase(value: Cat)
+}
+```
+
+`optional T` fields generate `Option[T]`. Reference tracking uses `@Ref`.
+
+### Registration
+
+Generated registration helpers register Scala serializers, enums, structs, and
+unions for `Fory` and `ThreadSafeFory`:
+
+```scala
+object AddressbookForyRegistration {
+  def register(fory: Fory): Unit = {
+    ScalaSerializers.registerSerializers(fory)
+    ScalaSerializers.registerEnum(fory, classOf[Person.PhoneType], 101L)
+    ForySerializer.register(fory, classOf[Person.PhoneNumber], 102L)
+    ForySerializer.register(fory, classOf[Person], 100L)
+    ForySerializer.register(fory, classOf[Animal], 106L)
+  }
+}
+```
+
+Run the end-to-end Scala IDL matrix with:
+
+```bash
+cd integration_tests/idl_tests
+./run_scala_tests.sh
+```
+
+The runner regenerates Scala fixtures, runs Scala 3 IDL tests, and then runs 
the
+Java peer matrix with `IDL_PEER_LANG=scala`.
+
 ## Cross-Language Notes
 
 ### Type ID Behavior
diff --git a/docs/compiler/index.md b/docs/compiler/index.md
index 286de0b5cc..e0317ed22b 100644
--- a/docs/compiler/index.md
+++ b/docs/compiler/index.md
@@ -21,7 +21,7 @@ license: |
 
 Fory IDL is a schema definition language for Apache Fory that enables type-safe
 cross-language serialization. Define your data structures once and generate
-native data structure code for Java, Python, Go, Rust, C++, C#, Swift, 
JavaScript, and Dart.
+native data structure code for Java, Python, Go, Rust, C++, C#, Swift, 
JavaScript, Dart, and Scala.
 
 ## Example Schema
 
@@ -104,6 +104,7 @@ Generated code uses native language constructs:
 - JavaScript: Interfaces with registration function
 - Swift: Fory model macros with field/case metadata and registration helpers
 - Dart: `@ForyStruct` classes with `@ForyField` annotations and registration 
helpers
+- Scala: Scala 3 `case class`, normal class, enum, and ADT enum models with 
macro-derived serializers
 
 ## Quick Start
 
@@ -141,7 +142,7 @@ message Person {
 foryc example.fdl --output ./generated
 
 # Generate for specific languages
-foryc example.fdl --lang java,python,csharp,javascript,swift,dart --output 
./generated
+foryc example.fdl --lang java,python,csharp,javascript,swift,dart,scala 
--output ./generated
 ```
 
 ### 4. Use Generated Code
@@ -197,11 +198,11 @@ message Example {
 
 Fory IDL types map to native types in each language:
 
-| Fory IDL Type | Java      | Python         | Go       | Rust     | C++       
    | C#       | JavaScript | Swift    | Dart     |
-| ------------- | --------- | -------------- | -------- | -------- | 
------------- | -------- | ---------- | -------- | -------- |
-| `int32`       | `int`     | `pyfory.Int32` | `int32`  | `i32`    | `int32_t` 
    | `int`    | `number`   | `Int32`  | `int`    |
-| `string`      | `String`  | `str`          | `string` | `String` | 
`std::string` | `string` | `string`   | `String` | `String` |
-| `bool`        | `boolean` | `bool`         | `bool`   | `bool`   | `bool`    
    | `bool`   | `boolean`  | `Bool`   | `bool`   |
+| Fory IDL Type | Java      | Python         | Go       | Rust     | C++       
    | C#       | JavaScript | Swift    | Dart     | Scala     |
+| ------------- | --------- | -------------- | -------- | -------- | 
------------- | -------- | ---------- | -------- | -------- | --------- |
+| `int32`       | `int`     | `pyfory.Int32` | `int32`  | `i32`    | `int32_t` 
    | `int`    | `number`   | `Int32`  | `int`    | `Int`     |
+| `string`      | `String`  | `str`          | `string` | `String` | 
`std::string` | `string` | `string`   | `String` | `String` | `String`  |
+| `bool`        | `boolean` | `bool`         | `bool`   | `bool`   | `bool`    
    | `bool`   | `boolean`  | `Bool`   | `bool`   | `Boolean` |
 
 See [Type System](schema-idl.md#type-system) for complete mappings.
 
diff --git a/docs/compiler/schema-idl.md b/docs/compiler/schema-idl.md
index b7252ed6a8..ab98a0e07f 100644
--- a/docs/compiler/schema-idl.md
+++ b/docs/compiler/schema-idl.md
@@ -817,7 +817,8 @@ message Person [id=100] {
 
 ### Rules
 
-- Case IDs must be unique within the union
+- Case IDs must be positive and unique within the union
+- Case ID `0` is reserved for language runtimes that expose an unknown-case 
carrier
 - Cases cannot be `optional` or `ref`
 - Union cases do not support field options
 - Case types can be primitives, enums, messages, or other named types
@@ -845,8 +846,7 @@ field_type field_name = field_number;
 ```protobuf
 optional list<string> tags = 1;  // Nullable list
 list<optional string> tags = 2;  // Elements may be null
-ref list<Node> nodes = 3;        // Collection tracked as a reference
-list<ref Node> nodes = 4;        // Elements tracked as references
+list<ref Node> nodes = 3;        // Elements tracked as references
 ```
 
 **Grammar:**
@@ -859,8 +859,9 @@ list_type    := 'list' '<' { 'optional' | 'ref' | 
scalar_encoding } field_type '
 array_type   := 'array' '<' array_element_type '>'
 ```
 
-Modifiers apply to the field/collection. Use `list<...>` to describe element
-modifiers. `repeated` is accepted as an alias for `list`.
+`optional` before `list` applies to the collection field. `ref` is only valid
+for named message/union fields; for collection contents, use `list<ref T>` or
+`map<K, ref V>`. `repeated` is accepted as an alias for `list`.
 
 ### Field Modifiers
 
@@ -886,6 +887,7 @@ message User {
 | C++        | `std::string name` | `std::optional<std::string> name` |
 | JavaScript | `name: string`     | `name?: string \| null`           |
 | Dart       | `String name`      | `String? email`                   |
+| Scala      | `name: String`     | `email: Option[String]`           |
 
 **Default Values:**
 
@@ -916,13 +918,14 @@ message Node {
 
 | Language   | Without `ref`  | With `ref`                                 |
 | ---------- | -------------- | ------------------------------------------ |
-| Java       | `Node parent`  | `Node parent` with `@ForyField(ref=true)`  |
+| Java       | `Node parent`  | `Node parent` with `@Ref`                  |
 | Python     | `parent: Node` | `parent: Node = pyfory.field(ref=True)`    |
 | Go         | `Parent Node`  | `Parent *Node` with `fory:"ref"`           |
 | Rust       | `parent: Node` | `parent: Arc<Node>`                        |
 | C++        | `Node parent`  | `std::shared_ptr<Node> parent`             |
 | JavaScript | `parent: Node` | `parent: Node` (no ref distinction)        |
 | Dart       | `Node parent`  | `Node parent` with `@ForyField(ref: true)` |
+| Scala      | `parent: Node` | `parent: Node @Ref`                        |
 
 Rust uses `Arc` by default; use `ref(thread_safe=false)` or `ref(weak=true)`
 to customize pointer types. For protobuf option syntax, see
@@ -959,23 +962,22 @@ Modifiers can be combined:
 message Example {
     optional list<string> tags = 1;  // Nullable list
     list<optional string> aliases = 2; // Elements may be null
-    ref list<Node> nodes = 3;          // Collection tracked as a reference
-    list<ref Node> children = 4;       // Elements tracked as references
-    optional ref User owner = 5;          // Nullable tracked reference
+    list<ref Node> children = 3;       // Elements tracked as references
+    optional ref User owner = 4;       // Nullable tracked reference
 }
 ```
 
-Modifiers before `list` apply to the field/collection. Modifiers after `list`
-apply to elements. `repeated` is accepted as an alias for `list`.
+`optional` before `list` applies to the field/collection. `ref` before `list` 
or
+`map` is invalid; put `ref` inside the element/value type instead. `repeated` 
is
+accepted as an alias for `list`.
 
 **List modifier mapping:**
 
-| Fory IDL                | Java                                    | Python   
                               | Go                      | Rust                 
 | C++                                       | Dart                             
                             |
-| ----------------------- | --------------------------------------- | 
--------------------------------------- | ----------------------- | 
--------------------- | ----------------------------------------- | 
------------------------------------------------------------- |
-| `optional list<string>` | `@Nullable List<String>`                | 
`Optional[List[str]]`                   | `[]string` + `nullable` | 
`Option<Vec<String>>` | `std::optional<std::vector<std::string>>` | 
`List<String>?`                                               |
-| `list<optional string>` | `List<String>` (nullable elements)      | 
`List[Optional[str]]`                   | `[]*string`             | 
`Vec<Option<String>>` | `std::vector<std::optional<std::string>>` | 
`List<String?>`                                               |
-| `ref list<User>`        | `List<User>` + `@ForyField(ref = true)` | 
`List[User]` + `pyfory.field(ref=True)` | `[]User` + `ref`        | 
`Arc<Vec<User>>`      | `std::shared_ptr<std::vector<User>>`      | 
`List<User>` + `@ForyField(ref: true)`                        |
-| `list<ref User>`        | `List<User>`                            | 
`List[User]`                            | `[]*User` + `ref=false` | 
`Vec<Arc<User>>`      | `std::vector<std::shared_ptr<User>>`      | 
`List<User>` + `@ListField(element: DeclaredType(ref: true))` |
+| Fory IDL                | Java                               | Python        
        | Go                      | Rust                  | C++                 
                      | Dart                                                    
      | Scala                  |
+| ----------------------- | ---------------------------------- | 
--------------------- | ----------------------- | --------------------- | 
----------------------------------------- | 
------------------------------------------------------------- | 
---------------------- |
+| `optional list<string>` | `@Nullable List<String>`           | 
`Optional[List[str]]` | `[]string` + `nullable` | `Option<Vec<String>>` | 
`std::optional<std::vector<std::string>>` | `List<String>?`                     
                          | `Option[List[String]]` |
+| `list<optional string>` | `List<String>` (nullable elements) | 
`List[Optional[str]]` | `[]*string`             | `Vec<Option<String>>` | 
`std::vector<std::optional<std::string>>` | `List<String?>`                     
                          | `List[Option[String]]` |
+| `list<ref User>`        | `List<@Ref User>`                  | `List[User]`  
        | `[]*User` + `ref=false` | `Vec<Arc<User>>`      | 
`std::vector<std::shared_ptr<User>>`      | `List<User>` + `@ListField(element: 
DeclaredType(ref: true))` | `List[User @Ref]`      |
 
 Use `ref(thread_safe=false)` in Fory IDL (or `[(fory).thread_safe_pointer = 
false]` in protobuf)
 to generate `Rc` instead of `Arc` in Rust.
@@ -1360,6 +1362,11 @@ code. When `enable_auto_type_id = false`, types without 
explicit IDs are
 registered by namespace and name instead. Collisions are detected at
 compile-time across the current file and all imports; when a collision occurs,
 the compiler raises an error and asks for an explicit `id` or an `alias`.
+For Java and Scala generated code, nested name registration appends the parent
+path to the namespace and keeps the nested type's simple name. For example,
+`package demo; message Envelope { message Payload { ... } }` registers
+`Payload` as namespace `demo.Envelope` and type name `Payload` in those JVM
+targets.
 
 ```protobuf
 enum Color [id=100] { ... }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to