Skip to content

Commit 1d30d88

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 1d30d88

File tree

1 file changed

+69
-33
lines changed

1 file changed

+69
-33
lines changed

doc/classfile-spec.md

Lines changed: 69 additions & 33 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,9 +176,9 @@ 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
177-
- A non-empty work-class `-prefix=` is prepended to the normalized work-file stem
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 base type named by the project base class as its default class type name
181+
- A non-empty `-prefix=` on a work file kind is prepended to the normalized class file stem of a work classfile
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`,
180184
`chan`, `for`, `if`, `else`, `switch`, `case`, `select`, `defer`, `range`, `return`, `break`, `continue`,
@@ -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

@@ -409,20 +413,52 @@ For each `project` directive:
409413
pointer to the named base type rather than the base type itself
410414

411415
For each `class` directive:
412-
- The exported symbol names the work base class
416+
- The exported symbol names the work base class and is resolved from the framework package of the containing project
417+
group
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
415-
type
419+
- If a project group declares more than one work file kind, every work file kind in that group must declare a work
420+
prototype type
421+
- When a work prototype type is named, the exported symbol is resolved from the framework package of the containing
422+
project group
423+
- `-embed` causes the project class type to embed a field for each generated work class instance of that work file kind
416424
- `-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
425+
- `-surface=` names the work surface type of the declared work file kind and may appear at most once in a `class`
426+
directive
427+
- When `-surface=` is present, the named symbol must resolve to an exported interface type in the framework package of
428+
the containing project group
429+
- Within one project group, no two work file kinds may declare the same work surface type
418430

419431
For each `import` directive:
420432
- The imported package becomes available to classfiles as an auto-imported package name
421433
- If no explicit import name is supplied, the package's declared package name is used
422434
- If multiple `import` directives in the same project group resolve to the same auto-import name, the last directive
423435
wins
424436

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

427463
A test framework registration is a framework registration whose project extension has the suffix `test.gox`.
428464

@@ -434,35 +470,35 @@ For each framework registration, a package may contain at most one explicit proj
434470

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

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.
473+
If a framework registration provides a project base class but the package contains no explicit project classfile for
474+
that framework, the compiler still synthesizes a default project class type.
439475

440476
The synthesized project class has no source file of its own. Its type name is derived by the project type-naming rules
441477
described earlier.
442478

443-
### Work-instance assembly for project `Main`
479+
### Work instance assembly for project `Main`
444480

445481
For every non-test framework registration that provides a project base class, the compiler generates a project method
446482
named `Main` on the project class type. The project base class is therefore required to provide a method named `Main`.
447-
The generated project method constructs work-class instances and forwards them to the embedded project base-class method
483+
The generated project method constructs work class instances and forwards them to the embedded project base-class method
448484
`Main`.
449485

450486
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
487+
- If the framework has exactly one work file kind and that `Main` parameter is variadic, all work files of that kind are
488+
passed as variadic arguments
489+
- Otherwise, work files are grouped by their declared work prototype type and passed as slices in `Main` parameter order
454490

455-
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+
The project `Main` method constructs one fresh work class instance for each work file in the package. When `-embed` is
492+
present on the corresponding `class` directive, the freshly created work instance is also assigned into the
493+
corresponding embedded field on the project instance before the project `Main` call.
458494

459495
## Synthesized helper methods
460496

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

463499
### `Classfname`
464500

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

467503
```xgo
468504
func (this *T) Classfname() string
@@ -476,9 +512,9 @@ Examples:
476512

477513
### `Classclone`
478514

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.
515+
If the work prototype type contains a method named `Classclone`, the compiler generates a shallow-clone method named
516+
`Classclone` with no parameters other than the receiver. Its result list is adopted from the work prototype type's
517+
`Classclone` declaration.
482518

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

493529
If none exists, the compiler selects a class entrypoint as follows:
494530
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
531+
2. Among framework project groups, it prefers a unique project group whose explicit project classfile has a shadow entry
496532
3. If no such group exists, it prefers a unique remaining project group, including one that is represented only by a
497533
synthesized default project class
498534
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)