From: Robert Griesemer Date: Fri, 16 Jan 2009 22:12:50 +0000 (-0800) Subject: - language for export via capitalized identifiers X-Git-Tag: weekly.2009-11-06~2341 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=83c17606d76f30eafce660d6e64187e628ccb0d0;p=gostls13.git - language for export via capitalized identifiers - removed explicit "export" declarations and keyword - fixed a few glitches and adjusted examples (The details of what "export" mean should be clarified in the spec, this is just so we have a working doc for now.) R=r DELTA=131 (7 added, 63 deleted, 61 changed) OCL=22753 CL=22970 --- diff --git a/doc/go_spec.txt b/doc/go_spec.txt index 812c3bbdc5..b78d81c5c3 100644 --- a/doc/go_spec.txt +++ b/doc/go_spec.txt @@ -3,7 +3,7 @@ The Go Programming Language Specification (DRAFT) Robert Griesemer, Rob Pike, Ken Thompson -(January 7, 2009) +(January 16, 2009) ---- @@ -28,8 +28,6 @@ Timeline (9/5/08): Missing: -[ ] partial export of structs, methods -[ ] packages of multiple files [ ] Helper syntax for composite types: allow names/indices for maps/arrays, remove need for type in elements of composites @@ -92,6 +90,8 @@ Decisions in need of integration into the doc: Closed: +[x] packages of multiple files - we have a working approach +[x] partial export of structs, methods [x] new as it is now is weird - need to go back to previous semantics and introduce literals for slices, maps, channels - done [x] determine if really necessary to disallow array assignment - allow array assignment @@ -155,12 +155,11 @@ Contents Declarations and scope rules Predeclared identifiers - Exported declarations + Exported identifiers Const declarations Iota Type declarations Variable declarations - Export declarations Types Basic types @@ -284,17 +283,18 @@ A package is a collection of import, constant, type, variable, and function declarations. Each declaration binds an ``identifier'' with a program entity (such as a variable). -In particular, all identifiers in a package are either declared explicitly -within the package, arise from an import statement, or belong to a small set -of predeclared identifiers (such as "string"). +In particular, all identifiers occurring in a package are either declared +explicitly within the package, arise from an import declaration, or belong +to a small set of predeclared identifiers (such as "string"). Scoping follows the usual rules: The scope of an identifier declared within a ``block'' generally extends from the declaration of the identifier to the end of the block. An identifier shadows identifiers with the same name declared in outer scopes. Within a scope, an identifier can be declared at most once. -A package may mark explicitly declared identifiers for ``export'' to make them -visible to other source files in the same package, or to other packages. +Identifiers may be ``internal'' or ``exported''. Internal identifiers are only +accessible to files belonging to the package in which they are declared. +External identifiers are accessible to other packages. Typing, polymorphism, and object-orientation @@ -342,11 +342,6 @@ they are no longer accessible. There is no pointer arithmetic in Go. Values and references ---- -TODO -- revisit this section -- if we'd keep the * for maps and chans, all types would have value semantics - again - Most data types have value semantics, but their contents may be accessed through different pointers referring to the same object. However, some data types have reference semantics to facilitate common usage patterns @@ -423,32 +418,30 @@ Comments are // to end of line or /* */ without nesting and are treated as white Some Unicode characters (e.g., the character U+00E4) may be representable in two forms, as a single code point or as two code points. For simplicity of -implementation, Go treats these as distinct characters. +implementation, Go treats these as distinct characters: each Unicode code +point is a single character in Go. Characters ---- -In the grammar the term - - utf8_char +The following terms are used to denote specific Unicode character classes: -denotes an arbitrary Unicode code point encoded in UTF-8. Similarly, + unicode_char an arbitrary Unicode code point + unicode_letter a Unicode code point classified as "Letter" + capital_letter a Unicode code point classified as "Letter, uppercase" - non_ascii - -denotes the subset of "utf8_char" code points with values >= 128. +(The Unicode Standard, Section 4.5 General Category - Normative.) Letters and digits ---- - letter = "A" ... "Z" | "a" ... "z" | "_" | non_ascii. + letter = unicode_letter | "_" . decimal_digit = "0" ... "9" . octal_digit = "0" ... "7" . hex_digit = "0" ... "9" | "A" ... "F" | "a" ... "f" . -All non-ASCII code points are considered letters; digits are always ASCII. ---- @@ -467,12 +460,14 @@ type, a function, etc. identifier = letter { letter | decimal_digit } . +Exported identifiers (§Exported identifiers) start with a capital_letter. + a - _x - ThisIsVariable9 + _x9 + ThisVariableIsExported αβ -Some identifiers are predeclared (§Declarations). +Some identifiers are predeclared (§Predeclared identifiers). Numeric literals @@ -541,7 +536,7 @@ following differences: The rules are: char_lit = "'" ( unicode_value | byte_value ) "'" . - unicode_value = utf8_char | little_u_value | big_u_value | escaped_char . + unicode_value = unicode_char | little_u_value | big_u_value | escaped_char . byte_value = octal_byte_value | hex_byte_value . octal_byte_value = "\" octal_digit octal_digit octal_digit . hex_byte_value = "\" "x" hex_digit hex_digit . @@ -598,7 +593,7 @@ Double-quoted strings have the usual properties; back-quoted strings do not interpret backslashes at all. string_lit = raw_string_lit | interpreted_string_lit . - raw_string_lit = "`" { utf8_char } "`" . + raw_string_lit = "`" { unicode_char } "`" . interpreted_string_lit = """ { unicode_value | byte_value } """ . A string literal has type "string" (§Strings). Its value is constructed @@ -669,7 +664,7 @@ The following words are reserved and must not be used as identifiers: break default func interface select case else go map struct - chan export goto package switch + chan goto package switch const fallthrough if range type continue for import return var @@ -683,9 +678,7 @@ A declaration ``binds'' an identifier to a language entity (such as a package, constant, type, struct field, variable, parameter, result, function, method) and specifies properties of that entity such as its type. - Declaration = - [ "export" | "package" ] - ( ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl ) . + Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl . Every identifier in a program must be declared; some identifiers, such as "int" and "true", are predeclared (§Predeclared identifiers). @@ -726,9 +719,6 @@ same identifier declared in an outer block. function and does not intersect with any non-label scope. Thus, each function has its own private label scope. -An entity is said to be ``local'' to its scope. Declarations in the package -scope are ``global'' declarations. - Predeclared identifiers ---- @@ -753,36 +743,19 @@ The predeclared functions (note: this list is likely to change): cap(), convert(), len(), make(), new(), panic(), panicln(), print(), println(), typeof(), ... -Exported declarations +Exported identifiers ---- -Global declarations optionally may be marked for ``export'', thus making the -declared identifier accessible outside the current source file. Another source -file may then import the package (§Packages) and access exported identifiers -via qualified identifiers (§Qualified identifiers). Local declarations can -never be marked for export. - -There are two kinds of exports: If a declaration in a package P is marked with -the keyword "export", the declared identifier is accessible in any file -importing P; this is called ``unrestricted export''. If a declaration is -marked with the keyword "package", the declared identifier is only accessible -in files belonging to the same package P; this is called ``package-restricted'' -export. - -If the identifier represents a type, it must be a complete type (§Types) and -the type structure is exported as well. In particular, if the declaration -defines a "struct" or "interface" type, all structure fields and all structure -and interface methods are exported also. - - export const pi float = 3.14159265 - export func Parse(source string); +Identifiers that start with a capital_letter (§Identifiers) are ``exported'', +thus making the identifiers accessible outside the current package. A file +belonging to another package may then import the package (§Packages) and access +exported identifiers via qualified identifiers (§Qualified identifiers). - package type Node *struct { val int; next *Node } +All other identifiers are ``internal''; they are only visible in files +belonging to the same package which declares them. -TODO: Eventually we need to be able to restrict visibility of fields and methods. -(gri) The default should be no struct fields and methods are automatically exported. -Export should be identifier-based: an identifier is either exported or not, and thus -visible or not in importing package. +TODO: This should be made clearer. For instance, function-local identifiers +are never exported, but non-global fields/methods may be exported. Const declarations @@ -808,8 +781,8 @@ the type of all constants is the type specified, and the types of all expressions in ExpressionList must be assignment-compatible with the constant type. - const pi float64 = 3.14159265358979323846 - const e = 2.718281828 + const Pi float64 = 3.14159265358979323846 + const E = 2.718281828 const ( size int64 = 1024; eof = -1; @@ -836,6 +809,7 @@ ExpressionLists permit light-weight declaration of enumerated values (§Iota): Thursday; Friday; Partyday; + numberOfDays; // this constant in not exported ) The initializing expression for a numeric constant is evaluated @@ -985,7 +959,7 @@ of the variable. VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) . var i int - var u, v, w float + var U, V, W float var k = 0 var x, y float = -1.0, -2.0 var ( @@ -1014,7 +988,7 @@ The syntax is shorthand for - "var" ExpressionList = ExpressionList . + "var" IdentifierList = ExpressionList . i, j := 0, 10; f := func() int { return 7; } @@ -1024,36 +998,6 @@ Also, in some contexts such as "if", "for", or "switch" statements, this construct can be used to declare local temporary variables. -Export declarations ----- - -TODO: -1) rephrase this section (much of it covered by Exported declarations) -2) rethink need for this kind of export - -Global identifiers may be exported, thus making the -exported identifier visible outside the package. Another package may -then import the identifier to use it. - -Export declarations must only appear at the global level of a -source file and can name only globally-visible identifiers. -That is, one can export global functions, types, and so on but not -local variables or structure fields. - -Exporting an identifier makes the identifier visible externally to the -package. If the identifier represents a type, it must be a complete -type (§Types) and the type structure is -exported as well. The exported identifiers may appear later in the -source than the export directive itself, but it is an error to specify -an identifier not declared anywhere in the source file containing the -export directive. - - ExportDecl = [ "package" ] "export" ExportIdentifier { "," ExportIdentifier } . - ExportIdentifier = QualifiedIdent . - - export sin, cos - export math.abs - ---- Types @@ -1256,14 +1200,14 @@ types (§Types). struct { x, y int; u float; - a *[]int; - f *(); + A *[]int; + F *(); } A struct may contain ``anonymous fields'', which are declared with a type but no explicit field identifier. An anonymous field type must be specified as a type name "T", or as a pointer to a type name ``*T'', and T itself may not be -a pointer or interface type. The unqualified type acts as the field identifier. +a pointer or interface type. The unqualified type name acts as the field identifier. // A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4 struct { @@ -1422,13 +1366,13 @@ In general, a type implements an arbitrary number of interfaces. For instance, consider the interface type Lock interface { - lock, unlock (); + Lock, Unlock (); } If S1 and S2 also implement - func (p T) lock() { ... } - func (p T) unlock() { ... } + func (p T) Lock() { ... } + func (p T) Unlock() { ... } they implement the Lock interface as well as the File interface. @@ -3254,19 +3198,19 @@ The file must begin with a package clause. package Math -A package can gain access to exported items from another package +A package can gain access to exported identifiers from another package through an import declaration: ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) . ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] . ImportSpec = [ "." | PackageName ] PackageFileName . -An import statement makes the exported contents of the named -package file accessible in this package. +An import statement makes the exported top-level identifiers of the named +package file accessible to this package. In the following discussion, assume we have a package in the -file "/lib/math", called package Math, which exports functions sin -and cos. +file "/lib/math", called package "math", which exports the identifiers +"Sin" and "Cos" denoting the respective trigonometric functions. In the general form, with an explicit package name, the import statement declares that package name as an identifier whose @@ -3276,7 +3220,7 @@ For instance, after import M "/lib/math" the contents of the package /lib/math can be accessed by -M.cos, M.sin, etc. +"M.Sin", "M.Cos", etc. In its simplest form, with no package name, the import statement implicitly uses the imported package name itself as the local @@ -3284,7 +3228,7 @@ package name. After import "/lib/math" -the contents are accessible by Math.sin, Math.cos. +the contents are accessible by "math.Sin", "math.Cos". Finally, if instead of a package name the import statement uses an explicit period, the contents of the imported package are added @@ -3292,7 +3236,7 @@ to the current package. After import . "/lib/math" -the contents are accessible by sin and cos. In this instance, it is +the contents are accessible by "Sin" and "Cos". In this instance, it is an error if the import introduces name conflicts. Here is a complete example Go package that implements a concurrent prime sieve: @@ -3300,7 +3244,7 @@ Here is a complete example Go package that implements a concurrent prime sieve: package main // Send the sequence 2, 3, 4, ... to channel 'ch'. - func Generate(ch chan <- int) { + func generate(ch chan <- int) { for i := 2; ; i++ { ch <- i // Send 'i' to channel 'ch'. } @@ -3308,7 +3252,7 @@ Here is a complete example Go package that implements a concurrent prime sieve: // Copy the values from channel 'in' to channel 'out', // removing those divisible by 'prime'. - func Filter(in chan <- int, out *<-chan int, prime int) { + func filter(in chan <- int, out *<-chan int, prime int) { for { i := <-in; // Receive value of new variable 'i' from 'in'. if i % prime != 0 { @@ -3317,21 +3261,21 @@ Here is a complete example Go package that implements a concurrent prime sieve: } } - // The prime sieve: Daisy-chain Filter processes together. - func Sieve() { + // The prime sieve: Daisy-chain filter processes together. + func sieve() { ch := make(chan int); // Create a new channel. - go Generate(ch); // Start Generate() as a subprocess. + go generate(ch); // Start generate() as a subprocess. for { prime := <-ch; print(prime, "\n"); ch1 := make(chan int); - go Filter(ch, ch1, prime); + go filter(ch, ch1, prime); ch = ch1 } } func main() { - Sieve() + sieve() }