mirror of
https://github.com/cc65/cc65.git
synced 2025-04-13 06:37:20 +00:00
Started to explain scopes
git-svn-id: svn://svn.cc65.org/cc65/trunk@2714 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
1e2d7a03ff
commit
140dee0eea
205
doc/ca65.sgml
205
doc/ca65.sgml
@ -667,11 +667,148 @@ because they don't have a name which would allow to access them.
|
||||
|
||||
|
||||
|
||||
<sect>Scopes<label id="scopes">
|
||||
<sect>Scopes<label id="scopes"><p>
|
||||
|
||||
<p>
|
||||
ca65 implements several sorts of scopes for symbols.
|
||||
|
||||
<sect1>Global scope<p>
|
||||
|
||||
All (non cheap local) symbols that are declared outside of any nested scopes
|
||||
are in global scope.
|
||||
|
||||
|
||||
<sect1>A special scope: cheap locals<p>
|
||||
|
||||
A special scope is the scope for cheap local symbols. It lasts from one non
|
||||
local symbol to the next one, without any provisions made by the programmer.
|
||||
All other scopes differ in usage but use the same concept internally.
|
||||
|
||||
|
||||
<sect1>Generic nested scopes<p>
|
||||
|
||||
A nested scoped for generic use is started with <tt/<ref id=".SCOPE"
|
||||
name=".SCOPE">/ and closed with <tt/<ref id=".ENDSCOPE" name=".ENDSCOPE">/.
|
||||
The scope can have a name, in which case it is accessible from the outside by
|
||||
using <ref id="scopesyntax" name="explicit scopes">. If the scope does not
|
||||
have a name, all symbols created within the scope are local to the scope, and
|
||||
aren't accessible from the outside.
|
||||
|
||||
A nested scope can access symbols from the local or from enclosing scopes by
|
||||
name without using explicit scope names. In some cases there may be
|
||||
ambiguities, for example if there is a reference to a local symbol that is not
|
||||
yet defined, but a symbol with the same name exists in outer scopes:
|
||||
|
||||
<tscreen><verb>
|
||||
.scope outer
|
||||
foo = 2
|
||||
.scope inner
|
||||
lda #foo
|
||||
foo = 3
|
||||
.endscope
|
||||
.endscope
|
||||
</verb></tscreen>
|
||||
|
||||
In the example above, the <tt/lda/ instruction will load the value 3 into the
|
||||
accumulator, because <tt/foo/ is redefined in the scope. However:
|
||||
|
||||
<tscreen><verb>
|
||||
.scope outer
|
||||
foo = $1234
|
||||
.scope inner
|
||||
lda foo,x
|
||||
foo = $12
|
||||
.endscope
|
||||
.endscope
|
||||
</verb></tscreen>
|
||||
|
||||
Here, <tt/lda/ will still load from <tt/$12,x/, but since it is unknown to the
|
||||
assembler that <tt/foo/ is a zeropage symbol when translating the instruction,
|
||||
absolute mode is used instead. In fact, the assembler will not use absolute
|
||||
mode by default, but it will search through the enclosing scopes for a symbol
|
||||
with the given name. If one is found, the address size of this symbol is used.
|
||||
This may lead to errors:
|
||||
|
||||
<tscreen><verb>
|
||||
.scope outer
|
||||
foo = $12
|
||||
.scope inner
|
||||
lda foo,x
|
||||
foo = $1234
|
||||
.endscope
|
||||
.endscope
|
||||
</verb></tscreen>
|
||||
|
||||
In this case, when the assembler sees the symbol <tt/foo/ in the <tt/lda/
|
||||
instruction, it will search for an already defined symbol <tt/foo/. It will
|
||||
find <tt/foo/ in scope <tt/outer/, and a close look reveals that it is a
|
||||
zeropage symbol. So the assembler will use zeropage addressing mode. If
|
||||
<tt/foo/ is redefined later in scope <tt/inner/, the assembler tries to change
|
||||
the address in the <tt/lda/ instruction already translated, but since the new
|
||||
value needs absolute addressing mode, this fails, and an error message "Range
|
||||
error" is output.
|
||||
|
||||
Of course the most simple solution for the problem is to move the definition
|
||||
of <tt/foo/ in scope <tt/inner/ upwards, so it preceeds its use. There may be
|
||||
rare cases when this cannot be done. In these cases, you can use one of the
|
||||
address size override operators:
|
||||
|
||||
<tscreen><verb>
|
||||
.scope outer
|
||||
foo = $12
|
||||
.scope inner
|
||||
lda a:foo,x
|
||||
foo = $1234
|
||||
.endscope
|
||||
.endscope
|
||||
</verb></tscreen>
|
||||
|
||||
This will cause the <tt/lda/ instruction to be translated using absolute
|
||||
addressing mode, which means changing the symbol reference later does not
|
||||
cause any errors.
|
||||
|
||||
|
||||
<sect1>Nested procedures<p>
|
||||
|
||||
A nested procedure is created by use of <tt/<ref id=".PROC" name=".PROC">/. It
|
||||
differs from a <tt/<ref id=".SCOPE" name=".SCOPE">/ in that it must have a
|
||||
name, and a it will introduce a symbol with this name in the enclosing scope.
|
||||
So
|
||||
|
||||
<tscreen><verb>
|
||||
.proc foo
|
||||
...
|
||||
.endscope
|
||||
</verb></tscreen>
|
||||
|
||||
is actually the same as
|
||||
|
||||
<tscreen><verb>
|
||||
foo:
|
||||
.scope foo
|
||||
...
|
||||
.endscope
|
||||
</verb></tscreen>
|
||||
|
||||
This is the reason why a procedure must have a name. If you want a scope
|
||||
without a name, use <tt/<ref id=".SCOPE" name=".SCOPE">/.
|
||||
|
||||
<bf/Note:/ As you can see from the example above, scopes and symbols live in
|
||||
different namespaces. There can be a symbol named <tt/foo/ and a scope named
|
||||
<tt/foo/ without any conflicts (but see the section titled <ref
|
||||
id="scopesearch" name=""Scope search order"">).
|
||||
|
||||
|
||||
<sect1>Structs, unions and enums<p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<sect1>Explicit scope specification<label id="scopesyntax"><p>
|
||||
|
||||
|
||||
<sect1>Scope search order<label id="scopesearch"><p>
|
||||
|
||||
|
||||
|
||||
@ -1175,6 +1312,11 @@ Here's a list of all control commands and a description, what they do:
|
||||
End a <tt><ref id=".REPEAT" name=".REPEAT"></tt> block.
|
||||
|
||||
|
||||
<sect1><tt>.ENDSCOPE</tt><label id=".ENDSCOPE"><p>
|
||||
|
||||
End of local lexical level (see <tt/<ref id=".SCOPE" name=".SCOPE">/).
|
||||
|
||||
|
||||
<sect1><tt>.ENDSTRUCT</tt><label id=".ENDSTRUCT"><p>
|
||||
|
||||
Ends a struct definition. See the section named <ref id="structs"
|
||||
@ -2098,17 +2240,16 @@ Here's a list of all control commands and a description, what they do:
|
||||
|
||||
<sect1><tt>.PROC</tt><label id=".PROC"><p>
|
||||
|
||||
Start a nested lexical level. All new symbols from now on are in the local
|
||||
lexical level and are not accessible from outside. Symbols defined outside
|
||||
this local level may be accessed as long as their names are not used for new
|
||||
symbols inside the level. Symbols names in other lexical levels do not
|
||||
clash, so you may use the same names for identifiers. The lexical level ends
|
||||
when the <tt><ref id=".ENDPROC" name=".ENDPROC"></tt> command is read.
|
||||
Lexical levels may be nested up to a depth of 16.
|
||||
|
||||
The command may be followed by an identifier, in this case the
|
||||
identifier is declared in the outer level as a label having the value of
|
||||
the program counter at the start of the lexical level.
|
||||
Start a nested lexical level with the given name and adds a symbol with this
|
||||
name to the enclosing scope. All new symbols from now on are in the local
|
||||
lexical level and are accessible from outside only via <ref id="scopesyntax"
|
||||
name="explicit scope specification">. Symbols defined outside this local
|
||||
level may be accessed as long as their names are not used for new symbols
|
||||
inside the level. Symbols names in other lexical levels do not clash, so you
|
||||
may use the same names for identifiers. The lexical level ends when the
|
||||
<tt><ref id=".ENDPROC" name=".ENDPROC"></tt> command is read. Lexical levels
|
||||
may be nested up to a depth of 16 (this is an artificial limit to protect
|
||||
against errors in the source).
|
||||
|
||||
Note: Macro names are always in the global level and in a separate name
|
||||
space. There is no special reason for this, it's just that I've never
|
||||
@ -2128,7 +2269,8 @@ Here's a list of all control commands and a description, what they do:
|
||||
.endproc ; Leave lexical level
|
||||
</verb></tscreen>
|
||||
|
||||
See: <tt><ref id=".ENDPROC" name=".ENDPROC"></tt>
|
||||
See: <tt/<ref id=".ENDPROC" name=".ENDPROC">/ and <tt/<ref id=".SCOPE"
|
||||
name=".SCOPE">/
|
||||
|
||||
|
||||
<sect1><tt>.PSC02</tt><label id=".PSC02"><p>
|
||||
@ -2220,7 +2362,7 @@ Here's a list of all control commands and a description, what they do:
|
||||
|
||||
<tscreen><verb>
|
||||
; Reserve 12 bytes of memory with value $AA
|
||||
.res 12, $AA
|
||||
.res 12, $AA
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
@ -2256,6 +2398,39 @@ Here's a list of all control commands and a description, what they do:
|
||||
See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command.
|
||||
|
||||
|
||||
<sect1><tt>.SCOPE</tt><label id=".SCOPE"><p>
|
||||
|
||||
Start a nested lexical level with the given name. All new symbols from now
|
||||
on are in the local lexical level and are accessible from outside only via
|
||||
<ref id="scopesyntax" name="explicit scope specification">. Symbols defined
|
||||
outside this local level may be accessed as long as their names are not used
|
||||
for new symbols inside the level. Symbols names in other lexical levels do
|
||||
not clash, so you may use the same names for identifiers. The lexical level
|
||||
ends when the <tt><ref id=".ENDSCOPE" name=".ENDSCOPE"></tt> command is
|
||||
read. Lexical levels may be nested up to a depth of 16 (this is an
|
||||
artificial limit to protect against errors in the source).
|
||||
|
||||
Note: Macro names are always in the global level and in a separate name
|
||||
space. There is no special reason for this, it's just that I've never
|
||||
had any need for local macro definitions.
|
||||
|
||||
Example:
|
||||
|
||||
<tscreen><verb>
|
||||
.scope Error ; Start new scope named Error
|
||||
None = 0 ; No error
|
||||
File = 1 ; File error
|
||||
Parse = 2 ; Parse error
|
||||
.endproc ; Close lexical level
|
||||
|
||||
...
|
||||
lda #Error::File ; Use symbol from scope Error
|
||||
</verb></tscreen>
|
||||
|
||||
See: <tt/<ref id=".ENDSCOPE" name=".ENDSCOPE">/ and <tt/<ref id=".PROC"
|
||||
name=".PROC">/
|
||||
|
||||
|
||||
<sect1><tt>.SEGMENT</tt><label id=".SEGMENT"><p>
|
||||
|
||||
Switch to another segment. Code and data is always emitted into a
|
||||
|
Loading…
x
Reference in New Issue
Block a user