1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-25 19:29:49 +00:00

Document keywords and handle them better

This commit is contained in:
Karol Stasiak 2019-10-08 01:33:55 +02:00
parent 3d3089ee93
commit c61d044226
6 changed files with 149 additions and 9 deletions

View File

@ -36,6 +36,8 @@
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
* [List of keywords](lang/keywords.md)
## Library reference
* [`stdlib` module](stdlib/stdlib.md)

View File

@ -36,6 +36,8 @@
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
* [List of keywords](lang/keywords.md)
## Library reference
* [`stdlib` module](stdlib/stdlib.md)

113
docs/lang/keywords.md Normal file
View File

@ -0,0 +1,113 @@
[< back to index](../doc_index.md)
# List of keywords
## Normal keywords
### Top level keywords
These keywords can occur at the top level of the file:
import segment
array struct union enum alias
### Declaration modifiers
These keywords occur within variable, array and function declarations:
* Variable declaration modifiers: `const volatile register static stack`
* Function declaration modifiers: `asm inline noinline interrupt kernal_interrupt macro reentrant extern`
* Array declaration modifiers: `const`
* Common modifiers: `segment align`
### Statement keywords
These keywords occur within function bodies:
if else for while do
goto label
asm
return
### Sub-statement keywords
These keywords occur within bodies of certain other statements:
* for-loop directions: `to until downto parallelto parallel until`
* special return-dispatch branch: `default`
* loop control flow: `break continue`
## Contextual keywords
These are not considered keywords, but have special meaning in certain syntactical locations:
* special alignment constant: `fast`
* special array function: `file`
* text encoding names: `z defaultz scr scrz`; for the rest, see [the list of text encodings](./text.md)
`default` is also a name of a text encoding, but it's also a keyword
## Reserved identifiers
Most of reserved identifiers are considered keywords (i.e. you cannot override them, even locally).
Some are not, but overriding them is strongly discouraged and for highest code clarity should also be considered keywords.
The keyword status of those identifiers may change in the future.
### Built-in types
The following identifiers are considered keywords:
byte ubyte sbyte word long
pointer void bool
set_carry set_zero set_overflow set_negative
clear_carry clear_zero clear_overflow clear_negative
int16 int24 int32 int40 int 48 int56 int64 int72 int80 int88 int96 int104 int112 int120 int128
unsigned8 signed8
`farword` is a deprecated alias for `int24` and it is not a keyword. It will be removed in the future.
### Built-in constants
The following identifiers are considered keywords:
true false
The following identifiers are not considered keywords:
nullptr nullchar
### Built-in functions and operators
The following identifiers are considered keywords:
not hi lo nonet sizeof
The following identifiers are not considered keywords:
sin cos tan call
## Reserved field names
It is not allowed to define a struct or a union with a field with any of the following names:
pointer addr rawaddr return
## Preprocesor keywords
### Directives
#if #elseif #else #endif
#define #use
#pragma
#fatal #error #warn #info #infoeval
### Built-in functions
not hi lo defined if

View File

@ -30,6 +30,7 @@ nav:
- Inline 6502 assembly: lang/assembly.md
- Inline 8080/LR35902/Z80 assembly: lang/assemblyz80.md
- Reentrancy guidelines: lang/reentrancy.md
- List of keywords: lang/keywords.md
- Library reference:
- stdlib module: stdlib/stdlib.md
- string module: stdlib/string.md

View File

@ -505,8 +505,14 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
}
def assertNotDefined(name: String, position: Option[Position]): Boolean = {
if (builtinsAdded && Environment.keywords(name)) {
log.error(s"Cannot redefine a builtin keyword `$name`", position)
if (builtinsAdded && Environment.invalidNewIdentifiers(name)) {
if (Environment.predefinedFunctions(name)) {
log.error(s"Cannot redefine a builtin predefined function `$name`", position)
} else if (Environment.neverIdentifiers(name)) {
log.error(s"Cannot the keyword `$name` as a name", position)
} else if (Environment.invalidNewIdentifiers(name)) {
log.error(s"Cannot redefine a builtin predefined identifier `$name`", position)
}
false
} else if (things.contains(name) || parent.exists(_.things.contains(name)) || things.contains(name.stripPrefix(prefix))) {
if (!name.contains('.')){
@ -2120,13 +2126,30 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
}
object Environment {
// built-in special-cased functions; can be considered keywords by some:
val predefinedFunctions: Set[String] = Set("not", "hi", "lo", "nonet", "sizeof")
val keywords: Set[String] = Set(
"true", "false",
"byte", "sbyte", "word", "pointer", "void", "long",
"array", "const", "alias", "import", "static", "register", "stack", "volatile", "asm", "extern", "kernal_interrupt", "interrupt",
"for", "if", "do", "while", "else", "return", "default", "to", "until", "paralleluntil", "parallelto", "downto",
// built-in special-cased functions, not keywords, but assumed to work almost as such:
val specialFunctions: Set[String] = Set("sin", "cos", "tan", "call")
// keywords:
val neverIdentifiers: Set[String] = Set(
"array", "const", "alias", "import", "static", "register", "stack", "volatile", "asm", "extern", "kernal_interrupt", "interrupt", "reentrant", "segment",
"struct", "union", "enum",
"for", "if", "do", "while", "else", "return", "default",
"to", "until", "paralleluntil", "parallelto", "downto",
"break", "continue",
"inline", "noinline"
) ++ predefinedFunctions
// predefined identifiers that cannot be overridden and do not name a type:
val neverValidTypeIdentifiers: Set[String] = Set(
"true", "false",
) ++ neverIdentifiers
// predefined type identifiers:
val invalidNewIdentifiers: Set[String] = Set(
"byte", "sbyte", "word", "pointer", "void", "long", "bool",
"set_carry", "set_zero", "set_overflow", "set_negative",
"clear_carry", "clear_zero", "clear_overflow", "clear_negative",
"int8", "int16", "int24", "int32", "int40", "int48", "int56", "int64", "int72", "int80", "int88", "int96", "int104", "int112", "int120", "int128",
"signed8", "unsigned16") ++ neverValidTypeIdentifiers
// built-in special-cased field names; can be considered keywords by some:
val invalidFieldNames: Set[String] = Set("addr", "rawaddr", "pointer", "return")
}

View File

@ -486,7 +486,7 @@ abstract class MfParser[T](fileId: String, input: String, currentDirectory: Stri
bank <- bankDeclaration
flags <- functionFlags ~ HWS
returnType <- identifier ~ SWS
if !InvalidReturnTypes(returnType)
if !Environment.neverValidTypeIdentifiers(returnType)
name <- identifier ~ HWS
params <- "(" ~/ AWS ~/ (if (flags("asm")) asmParamDefinition else paramDefinition).rep(sep = AWS ~ "," ~/ AWS) ~ AWS ~ ")" ~/ AWS
alignment <- alignmentDeclaration(fastAlignmentForFunctions).? ~/ AWS
@ -735,5 +735,4 @@ object MfParser {
val functionFlags: P[Set[String]] = flags_("asm", "inline", "interrupt", "macro", "noinline", "reentrant", "kernal_interrupt")
val InvalidReturnTypes: Set[String] = Set("enum", "alias", "array", "const", "stack", "register", "static", "volatile", "import", "struct", "union")
}