diff --git a/doc/go_spec.html b/doc/go_spec.html index da6ff62c36..b5d2c798e7 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -6,7 +6,7 @@ Biggest open issues: [ ] Conversions: - current situation is messy - 2 (3?) different notations for the same thing - - unclear when a type guard is needed + - unclear when a type assertion is needed - unclear where conversions can be applied - for type T int; can we say T(3.0) ? - do we need channel conversion (channel direction) @@ -46,11 +46,11 @@ Wish list: Smaller issues: -[ ] need for type switch? (or use type guard with ok in tuple assignment?) +[ ] need for type switch? (or use type assertion with ok in tuple assignment?) [ ] Is . import implemented / do we still need it? [ ] Do we allow empty statements? If so, do we allow empty statements after a label? and if so, does a label followed by an empty statement (a semicolon) still denote - a for loop that is following, and can break L be used inside it? + a for loop that is following, and can break L be used inside it? Closed: @@ -573,10 +573,10 @@ types, the dynamic type is always the static type.
-Basic types include traditional arithmetic types, booleans, and strings. All are predeclared. +Basic types include traditional numeric types, booleans, and strings. All are predeclared.
-
The architecture-independent numeric types are:
@@ -624,7 +624,7 @@ To avoid portability issues all numeric types are distinct except
Conversions
are required when different numeric types are mixed in an expression
or assignment. For instance, int32
and int
-are not the same type even though they may have the same size on a
+are not the same type even though they may have the same size on a
particular architecture.
@@ -723,7 +723,7 @@ distinct arrays always represent distinct storage.
The array underlying a slice may extend past the end of the slice. -The capacity is a measure of that extent: it is the sum of +The capacity is a measure of that extent: it is the sum of the length of the slice and the length of the array beyond the slice; a slice of length up to that capacity can be created by `slicing' a new one from the original slice (§Slices). @@ -755,7 +755,7 @@ and parameters specifying the length and optionally the capacity: make([]T, length) make([]T, length, capacity) - +
The make()
call allocates a new, hidden array to which the returned
slice value refers. That is, calling make
@@ -820,7 +820,7 @@ struct {
*T2; // the field name is T2
P.T3; // the field name is T3
*P.T4; // the field name is T4
- x, y int;
+ x, y int;
}
@@ -1332,7 +1332,7 @@ Every identifier in a program must be declared.
Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl .- +
The scope of an identifier is the extent of source text within which the identifier denotes the bound entity. No identifier may be declared twice in a @@ -1362,14 +1362,14 @@ The scope of an identifier depends on the entity declared:
if
, for
,
+ init statement of an if
, for
,
or switch
statement, the
innermost surrounding block is the block associated
with that statement.Basic types: - bool byte float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 + bool byte float32 float64 int8 int16 int32 int64 + string uint8 uint16 uint32 uint64 Architecture-specific convenience types: float int uint uintptr @@ -1401,13 +1402,13 @@ Constants: true false iota nil Functions: - cap convert len make new panic panicln print println typeof (TODO: typeof??) + cap len make new panic panicln print println + (TODO: typeof??) Packages: - sys unsafe (TODO: does sys endure?) + sys (TODO: does sys endure?)-
@@ -1471,10 +1472,12 @@ const u, v float = 0, 3 // u = 0.0, v = 3.0
Within a parenthesized const
declaration list the
expression list may be omitted from any but the first declaration.
Such an empty list is equivalent to the textual substitution of the
-first preceding non-empty expression list. Omitting the list of
-expressions is therefore equivalent to repeating the previous list.
-The number of identifiers must be equal to the number of expressions
-in the previous list. Together with the iota
constant generator
+first preceding non-empty expression list.
+(TODO: Substitute type from that declaration too?)
+Omitting the list of expressions is therefore equivalent to
+repeating the previous list. The number of identifiers must be equal
+to the number of expressions in the previous list.
+Together with the iota
constant generator
(§Iota) this mechanism permits light-weight declaration of sequential values:
-count, error := os.Close(fd); // os.Close() returns two values +r, w := os.Pipe(fd); // os.Pipe() returns two values
@@ -1785,7 +1788,8 @@ type List struct {
A forward-declared type is incomplete (§Types) until it is fully declared. The full declaration must follow -before the end of the block containing the forward declaration. +before the end of the block containing the forward declaration; +it cannot be contained in an inner block.
Functions and methods may similarly be forward-declared by omitting their body. @@ -1826,12 +1830,12 @@ StringLit = string_lit { string_lit } .
-An operand is called constant if it is a literal of a basic type
-(including the predeclared constants true
and false
,
-and values denoted by iota
),
-the predeclared constant nil
, or a parenthesized
-constant expression (§Constant expressions). Constants have values that
-are known at compile time.
+A constant is a literal of a basic type
+(including the predeclared constants true
, false
+and nil
+and values denoted by iota
)
+or a constant expression (§Constant expressions).
+Constants have values that are known at compile time.
-QualifiedIdent = [ LocalPackageName "." ] [ PackageName "." ] identifier . +QualifiedIdent = [ [ LocalPackageName "." ] PackageName "." ] identifier . LocalPackageName = identifier . PackageName = identifier .@@ -1863,6 +1867,9 @@ mypackage.hiddenName mypackage.Math.Sin // if Math is declared in an intervening scope +TODO: 6g does not implement LocalPackageName. Is this new? +Is it needed? +
@@ -1969,7 +1976,7 @@ It consists of a specification of the function type and a function body.
FunctionLit = "func" Signature Block . -Block = "{" [ StatementList ] "}" . +Block = "{" StatementList "}" .
@@ -1994,21 +2001,21 @@ as they are accessible.Primary expressions
- +PrimaryExpr = Operand | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Slice | - PrimaryExpr TypeGuard | + PrimaryExpr TypeAssertion | PrimaryExpr Call . -Selector = "." identifier . -Index = "[" Expression "]" . -Slice = "[" Expression ":" Expression "]" . -TypeGuard = "." "(" Type ")" . -Call = "(" [ ExpressionList ] ")" . +Selector = "." identifier . +Index = "[" Expression "]" . +Slice = "[" Expression ":" Expression "]" . +TypeAssertion = "." "(" Type ")" . +Call = "(" [ ExpressionList ] ")" .@@ -2171,7 +2178,7 @@ Fora
of typeM
or*M
whereM
is a map type (§Map types):
x
must be of the same type as the key type of M
+ x
's type must be equal to the key type of M
and the map must contain an entry with key x
(but see special forms below)
a[x]
is the map value with key x
and the type of a[x]
is the value type of M
@@ -2234,7 +2241,7 @@ s := a[1:3];
-the slice s
has type []int
, length 2, and elements
+the slice s
has type []int
, length 2, capacity 3, and elements
@@ -2244,10 +2251,10 @@ s[1] == 3The slice length must be non-negative. -For arrays or strings, -the index values in the slice must be in bounds for the original -array or string; -for slices, the index values must be between 0 and the capacity of the slice. +For arrays or strings, the indexes +
If the sliced operand is a string, the result of the slice operation is another, new string (§String types). If the sliced operand is an array or slice, the result @@ -2255,7 +2262,7 @@ of the slice operation is a slice (§Slice types).
-
For an expression x
and a type T
, the primary expression
@@ -2267,27 +2274,26 @@ x.(T)
asserts that the value stored in x
is of type T
.
-The notation .(T)
is called a type guard, and x.(T)
is called
-a guarded expression. The type of x
must be an interface type.
+The notation x.(T)
is called a type assertion.
+The type of x
must be an interface type.
-More precisely, if T
is not an interface type, the type guard asserts
+More precisely, if T
is not an interface type, x.(T)
asserts
that the dynamic type of x
is identical to the type T
(§Type equality and identity).
-If T
is an interface type, the type guard asserts that the dynamic type
+If T
is an interface type, x.(T)
asserts that the dynamic type
of T
implements the interface T
(§Interface types).
-The type guard is said to succeed if the assertion holds.
TODO: gri wants an error if x is already of type T.
-If the type guard succeeds, the value of the guarded expression is the value
-stored in x
and its type is T
. If the type guard fails, a run-time
+If the type assertion holds, the value of the expression is the value
+stored in x
and its type is T
. If the type assertion is false, a run-time
exception occurs. In other words, even though the dynamic type of x
-is known only at run-time, the type of the guarded expression x.(T)
is
+is known only at run-time, the type of x.(T)
is
known to be T
in a correct program.
-If a guarded expression is used in an assignment of one of the special forms, +If a type assertion is used in an assignment of one of the special forms,
@@ -2296,12 +2302,12 @@ v, ok := x.(T)
-the result of the guarded expression is a pair of values with types (T, bool)
.
-If the type guard succeeds, the expression returns the pair (x.(T), true)
;
+the result of the assertion is a pair of values with types (T, bool)
.
+If the assertion holds, the expression returns the pair (x.(T), true)
;
otherwise, the expression returns (Z, false)
where Z
is the zero value for type T
(§The zero value).
No run-time exception occurs in this case.
-The type guard in this construct thus acts like a function call
+The type assertion in this construct thus acts like a function call
returning a value and a boolean indicating success. (§Assignments)
-Expression = UnaryExpr | Expression binaryOp UnaryExpr . +Expression = UnaryExpr | Expression binary_op UnaryExpr . UnaryExpr = PrimaryExpr | unary_op UnaryExpr . binary_op = log_op | com_op | rel_op | add_op | mul_op . @@ -2431,7 +2437,7 @@ The operand types in binary operations must be equal, with the following excepti or an ideal number that can be safely converted into an unsigned integer type (§Arithmetic operators). -
+For floating point numbers,
++x
is the same as x
,
+while -x
is the negation of x
.
+
+
,
-
, *
, and <<
are
computed modulo 2n, where n is the bit width of
the unsigned integer's type
-(§Arithmetic types). Loosely speaking, these unsigned integer operations
+(§Numeric types). Loosely speaking, these unsigned integer operations
discard high bits upon overflow, and programs may rely on ``wrap around''.
@@ -2845,7 +2856,9 @@ The type of a constant expression is determined by the type of its elements. If it contains only numeric literals, its type is ideal integer or ideal float (§Ideal number). Whether it is an integer or float depends on whether the value can be represented -precisely as an integer (123 vs. 1.23). The nature of the arithmetic +precisely as an integer (123 vs. 1.23). +(TODO: Not precisely true; 1. is an ideal float.) +The nature of the arithmetic operations within the expression depends, elementwise, on the values; for example, 3/2 is an integer division yielding 1, while 3./2. is a floating point division yielding 1.5. Thus @@ -2925,7 +2938,7 @@ which may be omitted only if the previous statement:
-A labeled statement may be the target of a goto
,
+A labeled statement may be the target of a goto
,
break
or continue
statement.
IncDecStat = Expression ( "++" | "--" ) .- +
The following assignment statements (§Assignments) are semantically
equivalent:
@@ -3027,7 +3040,8 @@ A tuple assignment assigns the individual elements of a multi-valued
operation to a list of variables. There are two forms. In the
first, the right hand operand is a single multi-valued expression
such as a function evaluation or channel or map operation (§Channel
-operations, §Map operations). The number of operands on the left
+operations, §Map operations) or a type assertion (§Type assertions).
+The number of operands on the left
hand side must match the number of values. For instance, If
f
is a function returning two values,
x
and the second to y
.
In the second form, the number of operands on the left must equal the number -of expressions on the right, each of which must be single-valued. The -expressions are assigned to temporaries and then the temporaries -are assigned to the variables. +of expressions on the right, each of which must be single-valued. +The expressions on the right are evaluated before assigning to +any of the operands on the left, but otherwise the evaluation +order is unspecified.
@@ -3078,12 +3093,12 @@ if x > 0 { }-
-An "if" statement may include a short variable declaration before the expression
-(§Short variable declarations).
-The scope of the declared variables extends to the end of the "if" statement
+
+An "if" statement may include a simple statement before the expression.
+The scope of any variables declared by that statement
+extends to the end of the "if" statement
and the variables are initialized once before the statement is entered.
-
+
if x := f(); x < y { @@ -3108,7 +3123,7 @@ A missing expression is equivalent to+true
.SwitchStat = "switch" [ [ SimpleStat ] ";" ] [ Expression ] "{" { CaseClause } "}" . -CaseClause = SwitchCase ":" [ StatementList ] . +CaseClause = SwitchCase ":" StatementList . SwitchCase = "case" ExpressionList | "default" .@@ -3124,38 +3139,39 @@ There can be at most one default case and it may appear anywhere in theIn a case or default clause, the last statement only may be a "fallthrough" statement -($Fallthrough statement) to +(§Fallthrough statement) to indicate that control should flow from the end of this clause to the first statement of the next clause. Otherwise control flows to the end of the "switch" statement.
Each case clause effectively acts as a block for scoping purposes -($Declarations and scope rules). +(§Declarations and scope rules).
-A "switch" statement may include a short variable declaration before the +A "switch" statement may include a simple statement before the expression. -The scope of the declared variables extends to the end of the "switch" statement -and the variables are initialized once before the statement is entered. +The scope of any variables declared by that statement +extends to the end of the "switch" statement +and the variables are initialized once before the statement is entered.
switch tag { - default: s3() - case 0, 1, 2, 3: s1() - case 4, 5, 6, 7: s2() +default: s3() +case 0, 1, 2, 3: s1() +case 4, 5, 6, 7: s2() } switch x := f(); { - case x < 0: return -x - default: return x +case x < 0: return -x +default: return x } switch { // missing expression means "true" - case x < y: f1(); - case x < z: f2(); - case x == 4: f3(); +case x < y: f1(); +case x < z: f2(); +case x == 4: f3(); }@@ -3192,7 +3208,7 @@ and a post statement, such as an assignment, an increment or decrement statement. The init statement (but not the post statement) may also be a short variable declaration; the scope of the variables it declares ends at the end of the statement -($Declarations and scope rules). +(§Declarations and scope rules).@@ -3206,7 +3222,7 @@ for i := 0; i < 10; i++ { f(i) }- +If non-empty, the init statement is executed once before evaluating the condition for the first iteration; @@ -3237,7 +3253,7 @@ RangeClause = IdentifierList ( "=" | ":=" ) "range" Expression .
The type of the right-hand expression in the "range" clause must be an array, slice or map, or a pointer to an array, slice or map. -The slice or map must not be
nil
. +The slice or map must not benil
(TODO: really?). The identifier list must contain one or two identifiers denoting the iteration variables. On each iteration, the first variable is set to the array or slice index or @@ -3249,9 +3265,9 @@ must be assignment compatible to the iteration variables.The iteration variables may be declared by the "range" clause (":="), in which -case their scope ends at the end of the "for" statement ($Declarations and +case their scope ends at the end of the "for" statement (§Declarations and scope rules). In this case their types are set to -the array index and element types, or the map key and value types, respectively. +
@@ -3279,15 +3295,13 @@ for key, value = range m {int
and the array element type, or the map key and value types, respectively. If the iteration variables are declared outside the "for" statement, after execution their values will be those of the last iteration.If map entries that have not yet been processed are deleted during iteration, they will not be processed. If map entries are inserted during iteration, the -behavior is implementation-dependent. Likewise, if the range variable is -assigned to during execution of the loop, the behavior is implementation- -dependent. +behavior is implementation-dependent, but each entry will be processed at most once.
Go statements
-A "go" statement starts the execution of a function or method call +A "go" statement starts the execution of a function or method call as an independent concurrent thread of control, or goroutine, within the same address space.
@@ -3318,7 +3332,7 @@ cases all referring to communication operations.SelectStat = "select" "{" { CommClause } "}" . -CommClause = CommCase ":" [ StatementList ] . +CommClause = CommCase ":" StatementList . CommCase = "case" ( SendExpr | RecvExpr) | "default" . SendExpr = Expression "<-" Expression . RecvExpr = [ Expression ( "=" | ":=" ) ] "<-" Expression . @@ -3412,7 +3426,8 @@ func procedure() {There are two ways to return values from a function with a result type. The first is to explicitly list the return value or values -in the "return" statement. The expressions +in the "return" statement. +Normally, the expressions must be single-valued and assignment-compatible to the elements of the result type of the function.
@@ -3441,7 +3456,7 @@ func complex_f2() (re float, im float) {-Another method to return values is to use the elements of the +The second way to return values is to use the elements of the result list of the function as variables. When the function begins execution, these variables are initialized to the zero values for their type (§The zero value). The function can assign them as @@ -3457,6 +3472,10 @@ func complex_f3() (re float, im float) { }
+TODO: Define when return is required. +
+@@ -3527,6 +3546,7 @@ L:
is erroneous because the jump to label L
skips
the creation of v
.
+(TODO: Eliminate in favor of used and not set errors?)
v
.
A "fallthrough" statement transfers control to the first statement of the next case clause in a "switch" statement (§Switch statements). It may -be used only as the lexically last statement in a case or default clause in a +be used only as the final non-empty statement in a case or default clause in a "switch" statement.
@@ -3778,7 +3798,7 @@ to which it belongs, followed by a possibly empty set of import declarations that declare packages whose contents it wishes to use, followed by a possibly empty set of declarations of functions, types, variables, and constants. The source text following the -package clause acts as a block for scoping ($Declarations and scope +package clause acts as a block for scoping (§Declarations and scope rules). @@ -4113,7 +4133,7 @@ uintptr(unsafe.Pointer(&x)) % uintptr(unsafe.Alignof(x)) == 0
The maximum alignment is given by the constant Maxalign
.
It usually corresponds to the value of Sizeof(x)
for
-a variable x
of the largest arithmetic type (8 for a
+a variable x
of the largest numeric type (8 for a
float64
), but may
be smaller on systems with weaker alignment restrictions.
Alignof
, Offsetof
, and
type size in bytes @@ -4142,7 +4162,7 @@ The following minimal alignment properties are guaranteed:
- For a variable
x
of any type:1 <= unsafe.Alignof(x) <= unsafe.Maxalign
. -- For a variable
x
of arithmetic type:unsafe.Alignof(x)
is the smaller +- For a variable
x
of numeric type:unsafe.Alignof(x)
is the smaller ofunsafe.Sizeof(x)
andunsafe.Maxalign
, but at least 1.- For a variable
x
of struct type:unsafe.Alignof(x)
is the largest of @@ -4167,7 +4187,7 @@ cap() does not work on maps or chans.
len() does not work on chans.
-Conversions work for any type; doc says only arithmetic types and strings. +Conversions work for any type; doc says only numeric types and strings.