Skip to content

Commit 19a73aa

Browse files
committed
docs(classfile): add work surface type metadata
Define `work surface type` as optional classfile metadata for a work file kind and specify its validation and conformance rules. This also regularizes related terminology in `classfile-spec.md`, including `project file kind`, `work file kind`, and `work prototype type`, so the new metadata fits the existing classification and assembly rules. Updates #2700 Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
1 parent be09c49 commit 19a73aa

File tree

1 file changed

+61
-26
lines changed

1 file changed

+61
-26
lines changed

doc/classfile-spec.md

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ There are two kinds of classfiles:
1313
The following terms are used throughout this document:
1414
- Class extension: the normalized classfile suffix used for framework lookup, e.g., `_app.gox` and `.gsh`
1515
- Class file stem: the filename without the class extension
16+
- Project classfile: the framework file that represents the project-level class
17+
- Project file kind: a framework file kind declared by one `project` directive and used for project classfiles
18+
- Work classfile: a framework file that represents a non-project class within the same framework
19+
- Work file kind: a framework file kind declared by one `class` directive and used for work classfiles
1620
- Class type: the generated named type for a classfile
21+
- Base class: an embedded framework type declared by classfile metadata
22+
- Work prototype type: an exported type declared by classfile metadata and associated with one work file kind
23+
- Work surface type: an exported interface type declared by classfile metadata and associated with one work file kind
1724
- Field declaration block: the unique top-level `var` declaration that is interpreted as class fields rather than
1825
package variables
1926
- Shadow entry: the synthetic function created from top-level statements
20-
- Project classfile: the framework file that represents the project-level class
21-
- Work classfile: a framework file that represents a non-project class within the same framework
22-
- Base class: an embedded framework type declared by classfile metadata
2327

2428
## File classification
2529

@@ -172,8 +176,8 @@ Examples:
172176
- `get_p_#id_app.gox` has class file stem `get_p_#id` and normalized type name `get_p_id`
173177

174178
Framework metadata may further transform the type name:
175-
- A project file whose class file stem is `main`, or a framework that has no explicit project file, uses the project
176-
base-class name as its default class type name. A leading `*` on the base-class name is removed
179+
- A project classfile whose class file stem is `main`, or a framework that has no explicit project classfile, uses the
180+
name of the project base type as its default class type name
177181
- A non-empty work-class `-prefix=` is prepended to the normalized work-file stem
178182
- If neither of the previous rules applies and the class type name would otherwise equal one of the reserved names
179183
`init`, `main`, `go`, `goto`, `type`, `var`, `import`, `package`, `interface`, `struct`, `const`, `func`, `map`,
@@ -194,7 +198,7 @@ For a framework classfile, framework-added fields precede user fields.
194198

195199
Framework-added fields are inserted in the following order:
196200
- For a project classfile, the embedded project base class
197-
- For a project classfile, each embedded work-class field requested by the `-embed` flag, in work-class declaration
201+
- For a project classfile, each embedded work-class field requested by the `-embed` flag, in work file-kind declaration
198202
order and lexicographic source-file path order
199203
- For a work classfile, the embedded work base class
200204
- For a work classfile, an embedded pointer to the project class type, if a project class type exists and its field name
@@ -359,18 +363,18 @@ The classfile loader recognizes the following module directives:
359363
ProjectDirective = "project" [ ProjectExt ExportedName ] PackagePath { PackagePath } .
360364
ClassDirective = "class" { ClassDirectiveFlag } WorkExt ExportedName [ ExportedName ] .
361365
ImportDirective = "import" [ ImportName ] PackagePath .
362-
ClassDirectiveFlag = "-embed" | "-prefix=" string_without_space .
366+
ClassDirectiveFlag = "-embed" | "-prefix=" string_without_space | "-surface=" ExportedName .
363367
```
364368

365369
Every `class` or `import` directive belongs to the most recent preceding `project` directive.
366370

367371
A project group consists of one `project` directive together with all `class` and `import` directives that belong to it.
368372

369-
The first package path of a `project` directive is the framework package used to resolve any base-class symbols named by
370-
that project group.
373+
The first package path of a `project` directive is the framework package used to resolve the project base class, each
374+
work base class, each work prototype type, and each work surface type named by that project group.
371375

372-
Any additional package paths participate in implicit framework-package export lookup but are not searched for
373-
base-class symbols.
376+
Any additional package paths participate in implicit framework-package export lookup but are not searched for those
377+
symbols.
374378

375379
### Extension forms and normalization
376380

@@ -410,18 +414,49 @@ For each `project` directive:
410414

411415
For each `class` directive:
412416
- The exported symbol names the work base class
417+
- The first package path is the package from which that symbol is resolved
413418
- The optional final exported symbol is the work prototype type
414-
- If a project group declares more than one work class kind, every work class in that group must declare a prototype
419+
- If a project group declares more than one work file kind, every work file kind in that group must declare a prototype
415420
type
421+
- When a work prototype type is named, the first package path is the package from which that symbol is resolved
422+
- `-embed` causes the project class type to embed a field for each generated work class instance of that work file kind
416423
- `-prefix=` prepends the given string to every generated work class type name
417-
- `-embed` causes the project class type to embed a field for each generated work class instance of that work kind
424+
- `-surface=` names the work surface type of the declared work file kind and may appear at most once in a `class`
425+
directive
426+
- When `-surface=` is present, the named symbol must resolve to an exported interface type in the framework package of
427+
the containing project group
428+
- Within one project group, no two work file kinds may declare the same work surface type
418429

419430
For each `import` directive:
420431
- The imported package becomes available to classfiles as an auto-imported package name
421432
- If no explicit import name is supplied, the package's declared package name is used
422433
- If multiple `import` directives in the same project group resolve to the same auto-import name, the last directive
423434
wins
424435

436+
## Work surface types
437+
438+
For a work file kind that declares `-surface=`, the named interface type is the work surface type of that work file
439+
kind. The work surface type defines the public semantic surface of that work file kind. It is additional classfile
440+
metadata associated with that work file kind.
441+
442+
The work surface type is not a base class. It is not embedded into the generated work class type. It does not alter the
443+
lowered class type or its lowered methods.
444+
445+
The work surface type does not affect:
446+
- File classification
447+
- Class type naming
448+
- Field layout
449+
- Name resolution inside class methods
450+
- Project `Main` assembly
451+
- Synthesized helper-method generation
452+
453+
For every generated work class type `T` of that work file kind, `*T` must implement the work surface type of that work
454+
file kind. It is an error if, for any generated work class type `T` of that work file kind, `*T` does not implement the
455+
work surface type of that work file kind.
456+
457+
If no `-surface=` is declared for a work file kind, this specification defines no work surface type for that work file
458+
kind.
459+
425460
## Project and work-class assembly
426461

427462
A test framework registration is a framework registration whose project extension has the suffix `test.gox`.
@@ -434,8 +469,8 @@ For each framework registration, a package may contain at most one explicit proj
434469

435470
It is an error for a package to contain more than one explicit project classfile for the same framework registration.
436471

437-
If a framework registration provides a project base class but the package contains no explicit project file for that
438-
framework, the compiler still synthesizes a default project class type.
472+
If a framework registration provides a project base class but the package contains no explicit project classfile for
473+
that framework, the compiler still synthesizes a default project class type.
439474

440475
The synthesized project class has no source file of its own. Its type name is derived by the project type-naming rules
441476
described earlier.
@@ -448,21 +483,21 @@ The generated project method constructs work-class instances and forwards them t
448483
`Main`.
449484

450485
The grouping rule is:
451-
- If the framework has exactly one work class kind and that `Main` parameter is variadic, all work files of that kind
452-
are passed as variadic arguments
453-
- Otherwise, work files are grouped by their declared prototype type and passed as slices in `Main` parameter order
486+
- If the framework has exactly one work file kind and that `Main` parameter is variadic, all work files of that kind are
487+
passed as variadic arguments
488+
- Otherwise, work files are grouped by their declared work prototype type and passed as slices in `Main` parameter order
454489

455490
The project `Main` method constructs one fresh work-class instance for each work file in the package. When `-embed` is
456-
present on a work class declaration, the freshly created work instance is also assigned into the corresponding embedded
457-
field on the project instance before the project `Main` call.
491+
present on the corresponding `class` directive, the freshly created work instance is also assigned into the
492+
corresponding embedded field on the project instance before the project `Main` call.
458493

459494
## Synthesized helper methods
460495

461-
The compiler may synthesize additional work-class methods when the declared work prototype requires them.
496+
The compiler may synthesize additional work-class methods when the declared work prototype type requires them.
462497

463498
### `Classfname`
464499

465-
If the work prototype contains a method named `Classfname`, the compiler generates:
500+
If the work prototype type contains a method named `Classfname`, the compiler generates:
466501

467502
```xgo
468503
func (this *T) Classfname() string
@@ -476,9 +511,9 @@ Examples:
476511

477512
### `Classclone`
478513

479-
If the work prototype contains a method named `Classclone`, the compiler generates a shallow-clone method named
480-
`Classclone` with no parameters other than the receiver. Its result list is adopted from the prototype's `Classclone`
481-
declaration.
514+
If the work prototype type contains a method named `Classclone`, the compiler generates a shallow-clone method named
515+
`Classclone` with no parameters other than the receiver. Its result list is adopted from the work prototype type's
516+
`Classclone` declaration.
482517

483518
The generated implementation copies `*this` by value into a temporary variable and returns the address of that temporary
484519
value.
@@ -492,7 +527,7 @@ If one exists, no class-based package `main` is synthesized.
492527

493528
If none exists, the compiler selects a class entrypoint as follows:
494529
1. It considers only non-test framework registrations
495-
2. Among framework project groups, it prefers a unique project group whose explicit project file has a shadow entry
530+
2. Among framework project groups, it prefers a unique project group whose explicit project classfile has a shadow entry
496531
3. If no such group exists, it prefers a unique remaining project group, including one that is represented only by a
497532
synthesized default project class
498533
4. If no project group is selected, it selects the unique normal classfile that has a shadow entry, if exactly one

0 commit comments

Comments
 (0)