What is the rationale of the Go specification to define an identifier as exported
if both:
the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name or method name. "
The item 1. is clear to me.
But what is the intended meaning of the item 2. ?
As I understand every identifier must be declared in the package block, as Go does not offer other places to declare identifiers.
I also do not understand why the sentence seems to distinguish between identifiers and field names and method names. Aren't field names and method names examples of identifiers?
To ask differently: am I wrong thinking that:
there is no other way for an identifier to come to exist except
being declared in a package block (note a package block encompasses all package code)
field names and method names are identifiers
Identifiers are declarable solely in the package block
No identifier be declared outside a package block
Identifiers include struct field names and method names.
As denoted in the struct types section:
Field names may be specified explicitly (IdentifierList) or implicitly
(EmbeddedField)
In the following struct:
type s struct {
A int
b int
}
A is exported since it is a field name and starts with an uppercase character. b is not since it is a field name, but does not start with an uppercase character.
The same goes for method names (eg: (_ s) DoA() vs (_ s) doB()).
The confusion stems from the fact that you think identifiers are only at the package block level: they are not.
1. There is no other way for an identifier to come to exist except being declared in a package block
That's true. One thing that you're missing is scope of identifiers:
The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) and ends at the end of the innermost containing block
Which means that identifier declared inside function block, will not be available outside of this function.
2. Field names and method names are identifiers
True. As you can see in spec, MethodName is just an alias to identifier, same with field names.
3. Identifiers are declarable solely in the package block
I believe it's addressed by answer to 1st question.
4. No identifier can be declared outside a package block
There's predeclared identifiers that are declared in universe block. But you can't declare identifiers outside of package block in code.
Related
Please consider this pointcut expression:
#Before("execution(* org.mycompany.service.*.get*())")
I understand that an advice annotated by the expression above will execute for all methods who belong to a class in the package org.mycompany.service and whose names start with "get". My question is: what does the first asterick stand for? Is it a wildcard for access modifier or for return type?
From the reference documentation
The format of an execution expression follows:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
All parts except the returning type pattern (ret-type-pattern in the
preceding snippet), the name pattern, and the parameters pattern are
optional
So in the given code , first * represents ret-type-pattern
As a go beginner this always gets me whenever I start a new source file. So go's package clause defines the package name, without double quotes, since the package name must be an identifier, it cannot contains invalid chars like space or something. However, when it comes to import declarations, the package name must be double quoted, as the package name is exactly the one used in package clause, it must be identifier too(of course / is allowed as separator). It looks to me that would only add more key strokes without other benefits. I wonder why it is designed this way that imports must be double quoted strings.
Also, if we look at other languages, #include <foo.h>, using System.Bar, import java.lang.moo none of them requires imports to be strings.
A path a/b/foo is more like a string than an identifier: identifiers don't have separators, and paths may contain characters that aren't allowed in identifiers. You say package names can't contain spaces, which is true, but paths can, just as package names can't contain periods (.), but paths can. For example:
import "golang.org/x/exp/shiny/vendor/github.com/BurntSushi/xgb/render"`
This is mostly the same as C, which is listed in the question as not using strings to specify #include paths, but shares similarities with the go import statement. The two forms are both string-like: #include <a/b/foo.h> and #include "a/b/foo.h" although one uses <> rather than quotes to delimit the string.
For educational purposes, I'm trying to declare an alias to an enumeration value that is a character literal. In the example below, I'm trying to create the alias bit_one for the value '1' in enumeration type bit (declared in std.standard).
I am puzzled as to why the first form below is rejected by two compilers (GHDL 0.29.1 and Quartus II 13.01), while the second form is accepted by the same two, plus ModelSim and ActiveHDL. Hence the question: is it illegal to declare this alias as in the commented-out line below?
entity character_literal_alias is
end;
architecture rtl of character_literal_alias is
--alias bit_one is '1'[return bit]; -- Doesn't work in GHDL or Quartus
alias bit_one is std.standard.'1'[return bit]; -- Works with ModelSim, ActiveHDL, GHDL, and Quartus
alias append is append_mode[return file_open_kind]; -- Works with the whole bunch
begin
end;
I'm using the VHDL-2002 switch in GHDL and VHDL-2008 in the other tools.
If I were to speculate a little, in the VHDL-2008 LRM all the examples are written in the form:
-- implicit aliases ...
-- alias '0' is STD.STANDARD.'0' [return STD.STANDARD.BIT];
-- alias '1' is STD.STANDARD.'1' [return STD.STANDARD.BIT];
But those are implicit declarations, and even if the examples use selected names, it doesn't mean that every alias should be declared this way, IMO. So maybe some vendors misinterpreted the standard?
This actually relates to which VHDL tool is compliant to which standard revision
One of the two sets of VHDL analyzers is not compliant with the standard, but which standard revision?
ghdl says:
charlitalias.vhdl:5:22: identifier expected here
ghdl: compilation error
While not a particularly enlightening error message ghdl is by default IEEE Std 1076-1993 compliant by and large. ghdl defaults to --std=93c, which is -1993 compliant with relaxed rules relating to later standard changes. There are no standard changes affecting this question before -2008 revision, so --std=02 should have no bearing.
The following extracts are from the -1993 standard unless otherwise noted. Also note the EBNF found in the standard body is normative specifying syntax, while the text provides semantic specification.
4.3.3 Alias declarations
An alias declaration declares an alternate name for an existing named entity.
alias_declaration ::=
alias alias_designator [ : subtype_indication ] is name [ signature ] ;
Where:
name ::= [§ 6.1]
simple_name
| operator_symbol
| selected_name
| indexed_name
| slice_name
| attribute_name
The EBNF for name is updated in the -2008 standard, 8.1:
name ::=
simple_name
| operator_symbol
| character_literal
| selected_name
| indexed_name
| slice_name
| attribute_name
| external_name
In -2008 it includes a character literal, which is a lexical element.
This makes the example:
alias bit_one is '1'[return bit];
legal in -2008. A character literal can be treated as a name in the alias_declaration.
The example that worked universally specifies a selected name (an expanded name) with a suffix that is a character literal:
alias bit_one is std.standard.'1'[return bit];
The reason why a selected name works for a character literal is found in 6.3 Selected names, para 9:
An expanded name denotes a named entity declared in a package if the
prefix denotes the package and the suffix is the simple name,
character literal, or operator symbol of a named entity whose
declaration occurs immediately within that package.
Further that suffix is treated as if it were the name of a function:
3.1.1 Enumeration types, para 4:
The identifiers and character literals listed by an enumeration type
definition must be distinct within the enumeration type definition.
Each enumeration literal is the declaration of the corresponding
enumeration literal; for the purpose of determining the parameter and
result type profile of an enumeration literal, this declaration is
equivalent to the declaration of a parameterless function whose
designator is the same as the enumeration literal and whose result
type is the same as the enumeration type.
There's a bit of clarification in the -2008 standard, 5.2.2.1:
...,this declaration is equivalent to the declaration of a
parameterless function whose designator is the same as the enumeration
literal and whose result type is the same as the enumeration type; the
declaration is, nonetheless, a declaration of a literal, not of a
function.
The reason why this is of interest is because functions are named, operators are functions and operator symbols in double quotes are allowed as function names. There isn't anything allowing character literals as function names however.
Aliases are classified by whether or not they refer to objects (signals, constants, variables, files, named objects) or other named entities.
A nonobject alias (-1993 4.3.3.2, -2008 6.6.3) requires a signature for a character literal. The signature supplies a return type like a function, enabling overload resolution for the character literal, which by itself is ambiguous. Knowing the type is necessary to disambiguate the positional value of an enumeration literal. Take type BIT and type std_ulogic for instance. Both have '1' enumeration literals, yet the positional value (a natural) is 1 for BIT ('0', '1') and 3 for std_ulogic ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'). Evaluating expressions requires the positional value.
Back to ghdl/-1993:
So a selected name worked. A character literal by itself doesn't fit anywhere is in the -1993 expansion of name, but does for -2008.
If Modelsim and ActiveHDL were strictly -1993 compliant, they'd be in error. It's apparent in retrospect they are -2008 compliant which explains the difference in accepted syntax.
If they had been passed a flag to insure -1993 compliance Modelsim and ActiveHDL would have appeared to be treating the enumeration literal declaration as a function name had they accepted the alias declaration.
Prior to -2008 you couldn't treat a character literal as a name. You could always treat named enumeration literals as a name. You could imagine this disparity is why character_literal was added to name in -2008. Now all enumeration literals are 'named'.
So we get to the question:
But those are implicit declarations, and even if the examples use
selected names, it doesn't mean that every alias should be declared
this way, IMO. So maybe some vendors misinterpreted the standard?
The implicit alias declarations are syntactically and semantically correct representations found in the section on nonobject alias. They happen to be both compliant to both the -1993 and -2008 standards. Your example that fails in ghdl and passes in Modelsim isn't.
To maintain portability across revisions, use a selected name. You might gather adoption of new VHDL revisions lags significantly.
That's a critical mass issue, solved by first Jerry Kaczynski at Aldec driving ActiveHDL followed by Modelsim. The two open source implementations being actively developed I'm aware of are progressing toward -2008 compliance too.
I'm trying to pass a struct into a Go template using the built-in http/template library. I'm finding, though, that if I name the struct's variables with the first letters lowercase, they are not rendered in the template, but if I name them with the first letter uppercase, they are. I see here that structs can have both upper and lower case first letters. Why, then, does the Go templating engine not render both?
For examples, see:
Uppercase first letters
Lowercase first letters
Thanks in advance.
Simply put, the template engine can't see the members when they are written in lower case
as the template engine is in another package than your struct.
You may have noticed that Go does not use private or public keywords for visibility.
Instead, all functions, members, variables and the like are public when the first letter
of the identifier is in upper case. If the identifiers are not exported they can only
be used in the same package.
The spec on exporting identifiers:
An identifier may be exported to permit access to it from another
package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name or method name.
All other identifiers are not exported.
That is because the Go templating engine uses reflection to get the values out of types it doesn't "know" about. Only field names that begin with an uppercase letter are exported – and therefore available to the reflection model. See here for details on the rules of what gets exported and what does not:
[Where..] the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu")...
There are some other stipulations, but thats the most important one for this.
See this post for some great information on how reflection works in go.
lowercase means private in Go so the templating code is not allowed to access the fields.
Very basic question, but just reading through source code and trying to tell what the ' is for and how it differs from .
The ' character is used to introduce an attribute.
For example, Integer'Last is the largest value of type Integer, and Float'Digits is the decimal precision of type Float.
The complete list of language-defined attributes is in Annex K of the Ada Reference Manual.
It's also part of the syntax of qualified expressions, such as Some_Type'(expression).
The . character is used, among other things, to introduce a record component name, such as Obj.Comp, where Obj is a record variable and Comp is a component of that record.
Attributes are defined by the language or by the implementation; component names are defined when the record type is defined.
The apostrophe is also used to delimit character literals: 'x'.