From 36a0065b96c397474a73b82d80bb0b151c8ab6b0 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Fri, 21 Dec 2018 22:35:16 +0100 Subject: [PATCH] Forbid redefining builtins --- CHANGELOG.md | 2 ++ src/main/scala/millfork/env/Environment.scala | 30 ++++++++++++++++--- .../millfork/test/SeparateBytesSuite.scala | 6 ++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37be1aab..8380d29a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index 09417537..903c1645 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -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 } diff --git a/src/test/scala/millfork/test/SeparateBytesSuite.scala b/src/test/scala/millfork/test/SeparateBytesSuite.scala index c5373958..2ed77b1f 100644 --- a/src/test/scala/millfork/test/SeparateBytesSuite.scala +++ b/src/test/scala/millfork/test/SeparateBytesSuite.scala @@ -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