mirror of
https://github.com/KarolS/millfork.git
synced 2025-08-08 18:25:03 +00:00
Document keywords and handle them better
This commit is contained in:
@@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
|
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
|
||||||
|
|
||||||
|
* [List of keywords](lang/keywords.md)
|
||||||
|
|
||||||
## Library reference
|
## Library reference
|
||||||
|
|
||||||
* [`stdlib` module](stdlib/stdlib.md)
|
* [`stdlib` module](stdlib/stdlib.md)
|
||||||
|
@@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
|
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
|
||||||
|
|
||||||
|
* [List of keywords](lang/keywords.md)
|
||||||
|
|
||||||
## Library reference
|
## Library reference
|
||||||
|
|
||||||
* [`stdlib` module](stdlib/stdlib.md)
|
* [`stdlib` module](stdlib/stdlib.md)
|
||||||
|
113
docs/lang/keywords.md
Normal file
113
docs/lang/keywords.md
Normal 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
|
@@ -30,6 +30,7 @@ nav:
|
|||||||
- Inline 6502 assembly: lang/assembly.md
|
- Inline 6502 assembly: lang/assembly.md
|
||||||
- Inline 8080/LR35902/Z80 assembly: lang/assemblyz80.md
|
- Inline 8080/LR35902/Z80 assembly: lang/assemblyz80.md
|
||||||
- Reentrancy guidelines: lang/reentrancy.md
|
- Reentrancy guidelines: lang/reentrancy.md
|
||||||
|
- List of keywords: lang/keywords.md
|
||||||
- Library reference:
|
- Library reference:
|
||||||
- stdlib module: stdlib/stdlib.md
|
- stdlib module: stdlib/stdlib.md
|
||||||
- string module: stdlib/string.md
|
- string module: stdlib/string.md
|
||||||
|
37
src/main/scala/millfork/env/Environment.scala
vendored
37
src/main/scala/millfork/env/Environment.scala
vendored
@@ -505,8 +505,14 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
}
|
}
|
||||||
|
|
||||||
def assertNotDefined(name: String, position: Option[Position]): Boolean = {
|
def assertNotDefined(name: String, position: Option[Position]): Boolean = {
|
||||||
if (builtinsAdded && Environment.keywords(name)) {
|
if (builtinsAdded && Environment.invalidNewIdentifiers(name)) {
|
||||||
log.error(s"Cannot redefine a builtin keyword `$name`", position)
|
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
|
false
|
||||||
} else if (things.contains(name) || parent.exists(_.things.contains(name)) || things.contains(name.stripPrefix(prefix))) {
|
} else if (things.contains(name) || parent.exists(_.things.contains(name)) || things.contains(name.stripPrefix(prefix))) {
|
||||||
if (!name.contains('.')){
|
if (!name.contains('.')){
|
||||||
@@ -2120,13 +2126,30 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Environment {
|
object Environment {
|
||||||
|
// built-in special-cased functions; can be considered keywords by some:
|
||||||
val predefinedFunctions: Set[String] = Set("not", "hi", "lo", "nonet", "sizeof")
|
val predefinedFunctions: Set[String] = Set("not", "hi", "lo", "nonet", "sizeof")
|
||||||
val keywords: Set[String] = Set(
|
// built-in special-cased functions, not keywords, but assumed to work almost as such:
|
||||||
"true", "false",
|
val specialFunctions: Set[String] = Set("sin", "cos", "tan", "call")
|
||||||
"byte", "sbyte", "word", "pointer", "void", "long",
|
// keywords:
|
||||||
"array", "const", "alias", "import", "static", "register", "stack", "volatile", "asm", "extern", "kernal_interrupt", "interrupt",
|
val neverIdentifiers: Set[String] = Set(
|
||||||
"for", "if", "do", "while", "else", "return", "default", "to", "until", "paralleluntil", "parallelto", "downto",
|
"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"
|
"inline", "noinline"
|
||||||
) ++ predefinedFunctions
|
) ++ 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")
|
val invalidFieldNames: Set[String] = Set("addr", "rawaddr", "pointer", "return")
|
||||||
}
|
}
|
||||||
|
@@ -486,7 +486,7 @@ abstract class MfParser[T](fileId: String, input: String, currentDirectory: Stri
|
|||||||
bank <- bankDeclaration
|
bank <- bankDeclaration
|
||||||
flags <- functionFlags ~ HWS
|
flags <- functionFlags ~ HWS
|
||||||
returnType <- identifier ~ SWS
|
returnType <- identifier ~ SWS
|
||||||
if !InvalidReturnTypes(returnType)
|
if !Environment.neverValidTypeIdentifiers(returnType)
|
||||||
name <- identifier ~ HWS
|
name <- identifier ~ HWS
|
||||||
params <- "(" ~/ AWS ~/ (if (flags("asm")) asmParamDefinition else paramDefinition).rep(sep = AWS ~ "," ~/ AWS) ~ AWS ~ ")" ~/ AWS
|
params <- "(" ~/ AWS ~/ (if (flags("asm")) asmParamDefinition else paramDefinition).rep(sep = AWS ~ "," ~/ AWS) ~ AWS ~ ")" ~/ AWS
|
||||||
alignment <- alignmentDeclaration(fastAlignmentForFunctions).? ~/ 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 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")
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user