1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-12 22:29:33 +00:00

Forbid redefining builtins

This commit is contained in:
Karol Stasiak 2018-12-21 22:35:16 +01:00
parent e43fb39781
commit 36a0065b96
3 changed files with 31 additions and 7 deletions

View File

@ -34,6 +34,8 @@
* Extra `z` at the name of the encoding means that the string is zero-terminated.
* **Potentially breaking change!** No longer allowed to define things with names that are keywords or builtins.
* **Potentially breaking change!** Curly braces in text literals are now used for escape sequences.
* **Potentially breaking change!** Changed the `c64_basic` module.

View File

@ -199,13 +199,20 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
things ++= tagged
}
var builtinsAdded: Boolean = false
val things: mutable.Map[String, Thing] = mutable.Map()
val pointiesUsed: mutable.Map[String, Set[String]] = mutable.Map()
val removedThings: mutable.Set[String] = mutable.Set()
def isKnownPointy(callee: String, variable: String): Boolean = {
root.pointiesUsed.get(callee).exists(_.contains(variable))
}
private def addThing(t: Thing, position: Option[Position]): Unit = {
assertNotDefined(t.name, position)
if (assertNotDefined(t.name, position)) {
things(t.name.stripPrefix(prefix)) = t
}
}
def removeVariable(str: String): Unit = {
log.trace("Removing variable: " + str)
@ -387,11 +394,19 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
BranchingOpcodeMapping(Opcode.BPL, IfFlagClear(ZFlag.S)),
BranchingOpcodeMapping(Opcode.BMI, IfFlagSet(ZFlag.S))),
None)
builtinsAdded = true
}
def assertNotDefined(name: String, position: Option[Position]): Unit = {
if (things.contains(name) || parent.exists(_.things.contains(name)))
log.fatal(s"`$name` is already defined", position)
def assertNotDefined(name: String, position: Option[Position]): Boolean = {
if (builtinsAdded && Environment.keywords(name)) {
log.error(s"Cannot redefine a builtin keyword `$name`", position)
false
} else if (things.contains(name) || parent.exists(_.things.contains(name))) {
log.error(s"`$name` is already defined", position)
false
} else {
true
}
}
def registerType(stmt: TypeDefinitionStatement): Unit = {
@ -1372,4 +1387,11 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
object Environment {
val predefinedFunctions = 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",
"inline", "noinline"
) ++ predefinedFunctions
}

View File

@ -75,8 +75,8 @@ class SeparateBytesSuite extends FunSuite with Matchers {
test("Magic split array") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)("""
| array hi [16] @$c000
| array lo [16] @$c010
| array high [16] @$c000
| array low [16] @$c010
| void main () {
| word a
| word b
@ -86,7 +86,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
| byte i
| i = 0
| while i < 16 {
| hi[i]:lo[i] = a
| high[i]:low[i] = a
| tmp = a
| tmp += b
| a = b