Skip to content

Commit

Permalink
Merge pull request #1952 from xushiwei/q
Browse files Browse the repository at this point in the history
Constant/variable expressions
  • Loading branch information
xushiwei authored Jul 28, 2024
2 parents 2f2c737 + 67ad0f2 commit 7856bd7
Showing 1 changed file with 105 additions and 1 deletion.
106 changes: 105 additions & 1 deletion doc/spec-mini.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ echo "Hello world"
echo("Hello world")
```

#### Builtin functions
### Built-in functions

TODO

Expand Down Expand Up @@ -652,3 +652,107 @@ TODO
##### Conversions from slice to array or array pointer

TODO

### Constant expressions

Constant expressions may contain only [constant](#constants) operands and are evaluated at compile time.

Untyped boolean, numeric, and string constants may be used as operands wherever it is legal to use an operand of boolean, numeric, or string type, respectively.

A constant [comparison](#comparison-operators) always yields an untyped boolean constant. If the left operand of a constant [shift expression](#operators) is an untyped constant, the result is an integer constant; otherwise it is a constant of the same type as the left operand, which must be of [integer type](#numeric-types).

Any other operation on untyped constants results in an untyped constant of the same kind; that is, a boolean, integer, floating-point, complex, or string constant. If the untyped operands of a binary operation (other than a shift) are of different kinds, the result is of the operand's kind that appears later in this list: integer, rune, floating-point, complex. For example, an untyped integer constant divided by an untyped complex constant yields an untyped complex constant.

```go
const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant)
const b = 15 / 4 // b == 3 (untyped integer constant)
const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant)
const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer division)
const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division)
const d = 1 << 3.0 // d == 8 (untyped integer constant)
const e = 1.0 << 3 // e == 8 (untyped integer constant)
const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32)
const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)
const h = "foo" > "bar" // h == true (untyped boolean constant)
const j = true // j == true (untyped boolean constant)
const k = 'w' + 1 // k == 'x' (untyped rune constant)
const l = "hi" // l == "hi" (untyped string constant)
const m = string(k) // m == "x" (type string)
const Σ = 1 - 0.707i // (untyped complex constant)
const Δ = Σ + 2.0e-4 // (untyped complex constant)
const Φ = iota*1i - 1/1i // (untyped complex constant)
```

Applying the built-in function `complex` to untyped integer, rune, or floating-point constants yields an untyped complex constant.

```go
const ic = complex(0, c) // ic == 3.75i (untyped complex constant)
const iΘ = complex(0, Θ) // iΘ == 1i (type complex128)
```

Constant expressions are always evaluated exactly; intermediate values and the constants themselves may require precision significantly larger than supported by any predeclared type in the language. The following are legal declarations:

```go
const Huge = 1 << 100 // Huge == 1267650600228229401496703205376 (untyped integer constant)
const Four int8 = Huge >> 98 // Four == 4 (type int8)
```

The divisor of a constant division or remainder operation must not be zero:

```go
3.14 / 0.0 // illegal: division by zero
```

The values of typed constants must always be accurately [representable]() by values of the constant type. The following constant expressions are illegal:

```go
uint(-1) // -1 cannot be represented as a uint
int(3.14) // 3.14 cannot be represented as an int
int64(Huge) // 1267650600228229401496703205376 cannot be represented as an int64
Four * 300 // operand 300 cannot be represented as an int8 (type of Four)
Four * 100 // product 400 cannot be represented as an int8 (type of Four)
```

The mask used by the unary bitwise complement operator ^ matches the rule for non-constants: the mask is all 1s for unsigned constants and -1 for signed and untyped constants.

```go
^1 // untyped integer constant, equal to -2
uint8(^1) // illegal: same as uint8(-2), -2 cannot be represented as a uint8
^uint8(1) // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE)
int8(^1) // same as int8(-2)
^int8(1) // same as -1 ^ int8(1) = -2
```

### Short variable declarations

A short variable declaration uses the syntax:

```go
varName[, ...] = expression[, ...]
```

It is shorthand for a regular [variable declaration]() with initializer expressions but no types:

```go
var varName[, ...] = expression[, ...]
```

For example:

```go
i, j := 0, 10
f := func() int { return 7 }
ints := make([]int)
r, w, _ := os.Pipe() // os.Pipe() returns a connected pair of Files and an error, if any
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
```

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-[blank]() variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original. The non-blank variable names on the left side of := must be [unique]().

```go
field1, offset := nextField(str, 0)
field2, offset := nextField(str, offset) // redeclares offset
x, y, x := 1, 2, 3 // illegal: x repeated on left side of :=
```

Short variable declarations may appear only inside functions. In some contexts such as the initializers for "[if]()", "[for]()", or "[switch]()" statements, they can be used to declare local temporary variables.

0 comments on commit 7856bd7

Please sign in to comment.