diff --git a/docs/lcb/notes/14893.md b/docs/lcb/notes/14893.md
new file mode 100644
index 00000000000..0cb26f38453
--- /dev/null
+++ b/docs/lcb/notes/14893.md
@@ -0,0 +1,17 @@
+# LiveCode Builder Language
+## Identifiers
+
+* Identifiers are now expected to match `[A-Z0-9_.]`.
+
+## Syntax
+
+* Syntax keywords are no longer permitted to match `[A-Z0-9_.]`.
+
+# LiveCode Builder Tools
+## lc-compile
+### Warnings
+
+* A new warning has been added for identifiers that may conflict with
+ syntax keywords.
+
+# [14893] Emit warnings for identifiers that may cause problems.
diff --git a/tests/lc-run/Makefile b/tests/lc-run/Makefile
index cc27f9fc893..87bd314d226 100644
--- a/tests/lc-run/Makefile
+++ b/tests/lc-run/Makefile
@@ -24,4 +24,6 @@ check:
$(LC_COMPILE) --modulepath $(TEST_DIR) --modulepath $(MODULE_DIR) \
lc-run-test.mlc --output $(TEST_DIR)/lc-run-test.lcm
$(LC_RUN) -l $(TEST_DIR)/lc-run-lib.lcm $(TEST_DIR)/lc-run-test.lcm
- test "`$(LC_RUN) -l $(TEST_DIR)/lc-run-lib.lcm --list-handlers $(TEST_DIR)/lc-run-test.lcm`" = "main"
+ test "`$(LC_RUN) -l $(TEST_DIR)/lc-run-lib.lcm --list-handlers $(TEST_DIR)/lc-run-test.lcm`" = "Main"
+ $(LC_RUN) $(TEST_DIR)/lc-run-lib.lcm
+ test "`$(LC_RUN) --list-handlers $(TEST_DIR)/lc-run-lib.lcm`" = "main"
diff --git a/tests/lc-run/lc-run-lib.mlc b/tests/lc-run/lc-run-lib.mlc
index 4ed2eef9992..67b5d7e54a9 100644
--- a/tests/lc-run/lc-run-lib.mlc
+++ b/tests/lc-run/lc-run-lib.mlc
@@ -1,6 +1,7 @@
module com.livecode.lc_run_lib
-public handler lib_main()
+-- Intentional lower-case handler name
+public handler main()
-- Do nothing
end handler
diff --git a/tests/lc-run/lc-run-test.mlc b/tests/lc-run/lc-run-test.mlc
index bc7563f5341..2a54c50a5f3 100644
--- a/tests/lc-run/lc-run-test.mlc
+++ b/tests/lc-run/lc-run-test.mlc
@@ -2,8 +2,8 @@ module com.livecode.lc_run_test
use com.livecode.lc_run_lib
-public handler main()
- lib_main()
+public handler Main()
+ main()
end handler
end module
diff --git a/tests/lcb/stdlib/arithmetic.lcb b/tests/lcb/stdlib/arithmetic.lcb
index 2f3d344e09c..913e7bb8ca3 100644
--- a/tests/lcb/stdlib/arithmetic.lcb
+++ b/tests/lcb/stdlib/arithmetic.lcb
@@ -18,12 +18,12 @@ along with LiveCode. If not see . */
module com.livecode.arithmetic.tests
public handler TestUnarySigns()
- variable t
- put 10 into t
- test "unary−" when -t is -10
+ variable tNum
+ put 10 into tNum
+ test "unary−" when -tNum is -10
- put -10 into t
- test "unary+" when +t is -10
+ put -10 into tNum
+ test "unary+" when +tNum is -10
end handler
public handler TestAdd()
@@ -176,11 +176,11 @@ public handler TestFormatString()
test diagnostic "TODO -1 formatted as string (bug 14594)"
broken test "format as string (int)" when (-1) formatted as string is "-1" because "bug 14546"
- variable t
- put (-1.0) formatted as string into t
+ variable tNum
+ put (-1.0) formatted as string into tNum
test diagnostic "TODO test full string, not just prefix"
- test diagnostic t
- test "format as string (real)" when t begins with "-1."
+ test diagnostic tNum
+ test "format as string (real)" when tNum begins with "-1."
end handler
public handler TestParseString()
@@ -199,12 +199,12 @@ end handler
public handler TestParseStringList()
test "parsed list" when ["-1", "+2.2"] parsed as list of number is [-1, 2.2]
- variable t
+ variable tList
parse ["-1", "+2.2", "x"] as list of number
- put the result into t
+ put the result into tList
- test "parse list (defined)" when element 1 to 2 of t is [-1, 2.2]
- test "parse list (undefined)" when element 3 of t is not defined
+ test "parse list (defined)" when element 1 to 2 of tList is [-1, 2.2]
+ test "parse list (undefined)" when element 3 of tList is not defined
end handler
end module
diff --git a/tests/lcb/stdlib/byte.lcb b/tests/lcb/stdlib/byte.lcb
index d1aff1a1a7b..44408dfa997 100644
--- a/tests/lcb/stdlib/byte.lcb
+++ b/tests/lcb/stdlib/byte.lcb
@@ -35,25 +35,25 @@ handler TestByteWithCode_Overflow()
return the byte with code 256
end handler
public handler TestByteWithCode()
- variable t
- put the byte with code 0 into t
+ variable tString
+ put the byte with code 0 into tString
- test "code->byte" when the number of bytes in t is 1
+ test "code->byte" when the number of bytes in tString is 1
MCUnitTestHandlerThrows(TestByteWithCode_Negative, "code->byte (negative)")
MCUnitTestHandlerThrows(TestByteWithCode_Overflow, "code->byte (overflow)")
end handler
handler TestCodeOfByte_Long()
- variable t
- put the byte with code 0 into t
- put t after t
- return the code of t
+ variable tString
+ put the byte with code 0 into tString
+ put tString after tString
+ return the code of tString
end handler
handler TestCodeOfByte_Empty()
- variable t
- put the empty data into t
- return the code of t
+ variable tString
+ put the empty data into tString
+ return the code of tString
end handler
public handler TestCodeOfByte()
test "byte->code" when the code of (the byte with code 1) is 1
diff --git a/tests/lcb/stdlib/char.lcb b/tests/lcb/stdlib/char.lcb
index 2bb3720e166..a51490909a1 100644
--- a/tests/lcb/stdlib/char.lcb
+++ b/tests/lcb/stdlib/char.lcb
@@ -27,29 +27,29 @@ end handler
----------------------------------------------------------------
handler TestPutChar_Zero()
- variable t
- put "xxx" into t
- put "." into char 0 of t
+ variable tString
+ put "xxx" into tString
+ put "." into char 0 of tString
end handler
handler TestPutChar_Before()
- variable t
- put "xxx" into t
- put "." into char -4 of t
+ variable tString
+ put "xxx" into tString
+ put "." into char -4 of tString
end handler
handler TestPutChar_After()
- variable t
- put "xxx" into t
- put "." into char 4 of t
+ variable tString
+ put "xxx" into tString
+ put "." into char 4 of tString
end handler
public handler TestPutChar()
- variable t
- put "xxx" into t
- put "." into char 2 of t
- test "put char (+ve)" when t is "x.x"
+ variable tString
+ put "xxx" into tString
+ put "." into char 2 of tString
+ test "put char (+ve)" when tString is "x.x"
- put "xxx" into t
- put "." into char -2 of t
- test "put char (-ve)" when t is "x.x"
+ put "xxx" into tString
+ put "." into char -2 of tString
+ test "put char (-ve)" when tString is "x.x"
MCUnitTestHandlerThrows(TestPutChar_Zero, "put char (0)")
MCUnitTestHandlerThrows(TestPutChar_Before, "put char (before)")
@@ -57,25 +57,23 @@ public handler TestPutChar()
end handler
handler TestGetChar_Zero()
- variable t
- put "xxx" into t
- get char 0 of t
+ variable tString
+ put "xxx" into tString
+ get char 0 of tString
end handler
handler TestGetChar_Before()
- variable t
- put char -4 of "xxx" into t
+ return char -4 of "xxx"
end handler
handler TestGetChar_After()
- variable t
- put char 4 of "xxx" into t
+ return char 4 of "xxx"
end handler
public handler TestGetChar()
- variable t
- put char 2 of "x.x" into t
- test "get char (+ve)" when t is "."
+ variable tString
+ put char 2 of "x.x" into tString
+ test "get char (+ve)" when tString is "."
- put char -2 of "x.x" into t
- test "get char (-ve)" when t is "."
+ put char -2 of "x.x" into tString
+ test "get char (-ve)" when tString is "."
MCUnitTestHandlerThrows(TestGetChar_Zero, "get char (0)")
MCUnitTestHandlerThrows(TestGetChar_Before, "get char (before)")
@@ -85,84 +83,84 @@ end handler
----------------------------------------------------------------
public handler TestRange()
- variable t
+ variable tString
-- Put into range
- put "xxxx" into t
- put "." into char 2 to 2 of t
- test "range (put, +ve, equal)" when t is "x.xx"
+ put "xxxx" into tString
+ put "." into char 2 to 2 of tString
+ test "range (put, +ve, equal)" when tString is "x.xx"
- put "." into char 2 to 3 of t
- test "range (put, +ve)" when t is "x.x"
+ put "." into char 2 to 3 of tString
+ test "range (put, +ve)" when tString is "x.x"
- put "xxxx" into t
- put "." into char -2 to -2 of t
- test "range (put, -ve, equal)" when t is "xx.x"
+ put "xxxx" into tString
+ put "." into char -2 to -2 of tString
+ test "range (put, -ve, equal)" when tString is "xx.x"
- put "." into char -3 to -2 of t
- test "range (put, -ve)" when t is "x.x"
+ put "." into char -3 to -2 of tString
+ test "range (put, -ve)" when tString is "x.x"
-- Get from range
- put "xx.x" into t
- test "range (get, +ve, equal)" when char 3 to 3 of t is "."
- test "range (get, +ve)" when char 2 to 3 of t is "x."
- test "range (get, +ve, equal)" when char -2 to -2 of t is "."
- test "range (get, +ve)" when char -3 to -2 of t is "x."
+ put "xx.x" into tString
+ test "range (get, +ve, equal)" when char 3 to 3 of tString is "."
+ test "range (get, +ve)" when char 2 to 3 of tString is "x."
+ test "range (get, +ve, equal)" when char -2 to -2 of tString is "."
+ test "range (get, +ve)" when char -3 to -2 of tString is "x."
end handler
----------------------------------------------------------------
handler TestFirst_GetEmpty()
- variable t
- put the first char of "" into t
+ return the first char of ""
end handler
handler TestFirst_PutEmpty()
- variable t
- put the first char of "" into t
+ variable tString
+ put "" into tString
+ put "xxx" into the first char of tString
end handler
public handler TestFirst()
- variable t
+ variable tString
- put "xxx" into t
- put "." into the first char of t
- test "first (put single)" when t is ".xx"
+ put "xxx" into tString
+ put "." into the first char of tString
+ test "first (put single)" when tString is ".xx"
- put "yz" into the first char of t
- test "first (put multiple)" when t is "yzxx"
+ put "yz" into the first char of tString
+ test "first (put multiple)" when tString is "yzxx"
- test "first (get)" when the first char of t is "y"
+ test "first (get)" when the first char of tString is "y"
- put "xyz" into t
- put t into the first char of t
- test "first (self)" when t is "xyzyz"
+ put "xyz" into tString
+ put tString into the first char of tString
+ test "first (self)" when tString is "xyzyz"
MCUnitTestHandlerThrows(TestFirst_GetEmpty, "first (get empty)")
MCUnitTestHandlerThrows(TestFirst_PutEmpty, "first (put empty)")
end handler
handler TestLast_GetEmpty()
- variable t
- put the last char of "" into t
+ return the last char of ""
end handler
handler TestLast_PutEmpty()
- variable t
- put the last char of "" into t
+ variable tString
+ put "" into tString
+ put "xxx" into the last char of tString
end handler
public handler TestLast()
- variable t
+ variable tString
- put "xxx" into t
- put "." into the last char of t
- test "last (put)" when t is "xx."
+ put "xxx" into tString
+ put "." into the last char of tString
+ test "last (put)" when tString is "xx."
- put "yz" into the last char of t
- test "last (put multiple)" when t is "xxyz"
+ put "yz" into the last char of tString
+ test "last (put multiple)" when tString is "xxyz"
- test "last (get)" when the last char of t is "z"
+ test "last (get)" when the last char of tString is "z"
- put "xyz" into t
- put t into the last char of t
- test "first (self)" when t is "xyxyz"
+ put "xyz" into tString
+ put tString into the last char of tString
+ test "first (self)" when tString is "xyxyz"
MCUnitTestHandlerThrows(TestLast_GetEmpty, "last (get empty)")
MCUnitTestHandlerThrows(TestLast_PutEmpty, "last (put empty)")
@@ -171,96 +169,96 @@ end handler
----------------------------------------------------------------
handler TestDeleteSingle_Zero()
- variable t
- put "x" into t
- delete char 0 of t
+ variable tString
+ put "x" into tString
+ delete char 0 of tString
end handler
handler TestDeleteSingle_Before()
- variable t
- put "x" into t
- delete char -2 of t
+ variable tString
+ put "x" into tString
+ delete char -2 of tString
end handler
handler TestDeleteSingle_After()
- variable t
- put "x" into t
- delete char 2 of t
+ variable tString
+ put "x" into tString
+ delete char 2 of tString
end handler
handler TestDeleteSingle_FirstEmpty()
- variable t
- put "" into t
- delete the first char of t
+ variable tString
+ put "" into tString
+ delete the first char of tString
end handler
handler TestDeleteSingle_LastEmpty()
- variable t
- put "" into t
- delete the last char of t
+ variable tString
+ put "" into tString
+ delete the last char of tString
end handler
public handler TestDeleteSingle()
- variable t
+ variable tString
- put "xyz" into t
- delete char 2 of t
- test "delete single (+ve)" when t is "xz"
+ put "xyz" into tString
+ delete char 2 of tString
+ test "delete single (+ve)" when tString is "xz"
- put "xyz" into t
- delete char -2 of t
- test "delete single (-ve)" when t is "xz"
+ put "xyz" into tString
+ delete char -2 of tString
+ test "delete single (-ve)" when tString is "xz"
MCUnitTestHandlerThrows(TestDeleteSingle_Zero, "delete (single, 0)")
MCUnitTestHandlerThrows(TestDeleteSingle_Before, "delete (single, before)")
MCUnitTestHandlerThrows(TestDeleteSingle_After, "delete (single, after)")
- put "xyz" into t
- delete the first char of t
- test "delete first" when t is "yz"
+ put "xyz" into tString
+ delete the first char of tString
+ test "delete first" when tString is "yz"
- put "xyz" into t
- delete the last char of t
- test "delete last" when t is "xy"
+ put "xyz" into tString
+ delete the last char of tString
+ test "delete last" when tString is "xy"
MCUnitTestHandlerThrows(TestDeleteSingle_FirstEmpty, "delete first (empty)")
MCUnitTestHandlerThrows(TestDeleteSingle_LastEmpty, "delete last (empty)")
end handler
handler TestDeleteRange_Zero()
- variable t
- put "xxx" into t
- delete char 0 to 0 of t
+ variable tString
+ put "xxx" into tString
+ delete char 0 to 0 of tString
end handler
handler TestDeleteRange_Reverse()
- variable t
- put "xxx" into t
- delete char 3 to 2 of t
+ variable tString
+ put "xxx" into tString
+ delete char 3 to 2 of tString
end handler
handler TestDeleteRange_After()
- variable t
- put "xyz" into t
- delete char 3 to 5 of t
+ variable tString
+ put "xyz" into tString
+ delete char 3 to 5 of tString
end handler
handler TestDeleteRange_Before()
- variable t
- put "xyz" into t
- delete char -5 to -3 of t
- test diagnostic t
+ variable tString
+ put "xyz" into tString
+ delete char -5 to -3 of tString
+ test diagnostic tString
end handler
public handler TestDeleteRange()
- variable t
+ variable tString
- put "xyz" into t
- delete char 2 to 2 of t
- test "delete range (+ve, equal)" when t is "xz"
+ put "xyz" into tString
+ delete char 2 to 2 of tString
+ test "delete range (+ve, equal)" when tString is "xz"
- put "xyz" into t
- delete char -2 to -2 of t
- test "delete range (-ve, equal)" when t is "xz"
+ put "xyz" into tString
+ delete char -2 to -2 of tString
+ test "delete range (-ve, equal)" when tString is "xz"
- put "wxyz" into t
- delete char 2 to 3 of t
- test "delete range (+ve)" when t is "wz"
+ put "wxyz" into tString
+ delete char 2 to 3 of tString
+ test "delete range (+ve)" when tString is "wz"
- put "wxyz" into t
- delete char -3 to -2 of t
- test "delete range (+ve)" when t is "wz"
+ put "wxyz" into tString
+ delete char -3 to -2 of tString
+ test "delete range (+ve)" when tString is "wz"
MCUnitTestHandlerThrows(TestDeleteRange_Zero, "delete range (0)")
MCUnitTestHandlerThrows(TestDeleteRange_Before, "delete range (before)")
@@ -272,7 +270,7 @@ end handler
public handler TestContainsChar()
test "char is in" when "y" is in "xyz"
- test "char isn't in" when not "w" is in "xyz"
+ test "char isn'tString in" when not "w" is in "xyz"
test diagnostic "TODO 'y' is not in 'xyz'"
end handler
@@ -407,16 +405,16 @@ handler TestCharWithCode_Negative()
return the char with code -1
end handler
public handler TestCharWithCode()
- variable t
+ variable tString
- put the char with code 120 into t
- test "code->byte" when t is "x"
+ put the char with code 120 into tString
+ test "code->byte" when tString is "x"
- put the char with code 8594 into t
- test "code->byte (BMP)" when t is "\u{2192}"
+ put the char with code 8594 into tString
+ test "code->byte (BMP)" when tString is "\u{2192}"
- put the char with code 119070 into t
- test "code->byte (SMP)" when t is "\u{1d11e}"
+ put the char with code 119070 into tString
+ test "code->byte (SMP)" when tString is "\u{1d11e}"
MCUnitTestHandlerThrows(TestCharWithCode_Negative, "code->byte (-ve)")
end handler
diff --git a/tests/lcb/stdlib/foreign.lcb b/tests/lcb/stdlib/foreign.lcb
index 72257ef62e0..fb8d84df1d4 100644
--- a/tests/lcb/stdlib/foreign.lcb
+++ b/tests/lcb/stdlib/foreign.lcb
@@ -21,8 +21,8 @@ use com.livecode.foreign
use com.livecode.__INTERNAL._testlib
handler TestZStringNative_Null()
- variable t as ZStringNative
- put "\u{0}" into t
+ variable tList as ZStringNative
+ put "\u{0}" into tList
end handler
public handler TestZStringNative()
-- bug 14826
@@ -32,8 +32,8 @@ public handler TestZStringNative()
end handler
handler TestZStringUTF16_Null()
- variable t as ZStringUTF16
- put "\u{0}" into t
+ variable tList as ZStringUTF16
+ put "\u{0}" into tList
end handler
public handler TestZStringUTF16()
variable tUTF16 as ZStringUTF16
diff --git a/tests/lcb/stdlib/list.lcb b/tests/lcb/stdlib/list.lcb
index 66f9aade533..c2521ec48f1 100644
--- a/tests/lcb/stdlib/list.lcb
+++ b/tests/lcb/stdlib/list.lcb
@@ -21,18 +21,18 @@ use com.livecode.list
use com.livecode.__INTERNAL._testlib
public handler TestEmpty()
- variable t
- put the empty list into t
- test "empty (empty)" when t is empty
- test "empty (empty list)" when t is the empty list
- test "empty (empty literal)" when t is []
- test "empty (no elements)" when the number of elements in t is 0
+ variable tList
+ put the empty list into tList
+ test "empty (empty)" when tList is empty
+ test "empty (empty list)" when tList is the empty list
+ test "empty (empty literal)" when tList is []
+ test "empty (no elements)" when the number of elements in tList is 0
end handler
public handler TestLiteral()
- variable t
- put [[], "x", 1, true] into t
- test "literal" when the number of elements in t is 4
+ variable tList
+ put [[], "x", 1, true] into tList
+ test "literal" when the number of elements in tList is 4
end handler
public handler TestIs()
@@ -47,11 +47,11 @@ handler TestHead_FirstEmpty()
return the first element of []
end handler
public handler TestHead()
- variable t
- put ["x", 1, true] into t
+ variable tList
+ put ["x", 1, true] into tList
- test "head" when the head of t is "x"
- test "first" when the first element of t is "x"
+ test "head" when the head of tList is "x"
+ test "first" when the first element of tList is "x"
MCUnitTestHandlerThrows(TestHead_Empty, "head (empty)")
MCUnitTestHandlerThrows(TestHead_FirstEmpty, "first (empty)")
@@ -64,45 +64,45 @@ handler TestTail_LastEmpty()
return the last element of []
end handler
public handler TestTail()
- variable t
- put ["x", 1, true] into t
- test "tail" when the tail of t
- test "last" when the last element of t
+ variable tList
+ put ["x", 1, true] into tList
+ test "tail" when the tail of tList
+ test "last" when the last element of tList
MCUnitTestHandlerThrows(TestTail_Empty, "tail (empty)")
MCUnitTestHandlerThrows(TestTail_LastEmpty, "last (empty)")
end handler
public handler TestPush()
- variable t
- put ["x", 1, true] into t
+ variable tList
+ put ["x", 1, true] into tList
- push "y" onto t
- test "push" when the tail of t is "y"
+ push "y" onto tList
+ test "push" when the tail of tList is "y"
- push "z" onto front of t
- test "push front" when the head of t is "z"
+ push "z" onto front of tList
+ test "push front" when the head of tList is "z"
- push "w" onto back of t
- test "push back" when the tail of t is "w"
+ push "w" onto back of tList
+ test "push back" when the tail of tList is "w"
- test "push (result)" when t is ["z", "x", 1, true, "y", "w"]
+ test "push (result)" when tList is ["z", "x", 1, true, "y", "w"]
end handler
handler TestPop_Empty()
- variable t
- put [] into t
- pop t
+ variable tList
+ put [] into tList
+ pop tList
end handler
handler TestPop_FrontEmpty()
- variable t
- put [] into t
- pop front of t
+ variable tList
+ put [] into tList
+ pop front of tList
end handler
handler TestPop_BackEmpty()
- variable t
- put [] into t
- pop back of t
+ variable tList
+ put [] into tList
+ pop back of tList
end handler
public handler TestPop()
variable tList
@@ -134,18 +134,18 @@ public handler TestCount()
end handler
public handler TestContainsELement()
- variable t
- put ["x", 1, true] into t
- test "element is in" when "x" is in t
- test "element is not in" when not [] is in t
+ variable tList
+ put ["x", 1, true] into tList
+ test "element is in" when "x" is in tList
+ test "element is not in" when not [] is in tList
end handler
public handler TestContainsList()
- variable t
- put ["x", 1, true, []] into t
- test "contains" when t contains ["x", 1]
+ variable tList
+ put ["x", 1, true, []] into tList
+ test "contains" when tList contains ["x", 1]
- test "contains (missing)" when not t contains [1, "x"]
+ test "contains (missing)" when not tList contains [1, "x"]
test "contains (empty)" when not [] contains []
-- Bug 14596
@@ -153,19 +153,19 @@ public handler TestContainsList()
end handler
public handler TestBeginsWith()
- variable t
- put ["x", 1, true, []] into t
- test "begins with" when t begins with ["x", 1]
- test "begins with (missing)" when not t begins with [1, true]
- test "begins with (empty)" when t begins with []
+ variable tList
+ put ["x", 1, true, []] into tList
+ test "begins with" when tList begins with ["x", 1]
+ test "begins with (missing)" when not tList begins with [1, true]
+ test "begins with (empty)" when tList begins with []
end handler
public handler TestEndsWith()
- variable t
- put ["x", 1, true, []] into t
- test "ends with" when t ends with [true, []]
- test "ends with (missing)" when not t ends with [1, true]
- test "ends with (empty)" when t ends with []
+ variable tList
+ put ["x", 1, true, []] into tList
+ test "ends with" when tList ends with [true, []]
+ test "ends with (missing)" when not tList ends with [1, true]
+ test "ends with (empty)" when tList ends with []
end handler
handler TestSubscript_Zero()
@@ -181,12 +181,12 @@ handler TestSubscript_Before()
return[1][-2]
end handler
public handler TestSubscript()
- variable t
- put ["x", 1, true, []] into t
- test "subscript (syntax, +ve)" when element 2 of t is 1
- test "subscript (syntax, -ve)" when element -2 of t is true
- test "subscript (operator, +ve)" when t[4] is []
- test "subscript (operator, -ve)" when t[-4] is "x"
+ variable tList
+ put ["x", 1, true, []] into tList
+ test "subscript (syntax, +ve)" when element 2 of tList is 1
+ test "subscript (syntax, -ve)" when element -2 of tList is true
+ test "subscript (operator, +ve)" when tList[4] is []
+ test "subscript (operator, -ve)" when tList[-4] is "x"
test "subscript (operator literal)" when [4][1] is 4
MCUnitTestHandlerThrows(TestSubscript_Zero, "subscript (operator, zero)")
@@ -199,19 +199,19 @@ handler TestRange_Zero()
return element 0 to 0 of [1]
end handler
handler TestRange_Before()
- variable t
- put element -4 to -3 of ["x", 1, true] into t
+ variable tList
+ put element -4 to -3 of ["x", 1, true] into tList
end handler
handler TestRange_After()
return element 3 to 4 of ["x", 1, true]
end handler
public handler TestRange()
- variable t
- put ["x", 1, true, []] into t
- test "range (+ve)" when element 2 to 3 of t is [1, true]
- test "range (+ve, same)" when element 2 to 2 of t is [1]
- test "range (-ve)" when element -3 to -2 of t is [1, true]
- test "range (-ve, same)" when element -2 to -2 of t is [true]
+ variable tList
+ put ["x", 1, true, []] into tList
+ test "range (+ve)" when element 2 to 3 of tList is [1, true]
+ test "range (+ve, same)" when element 2 to 2 of tList is [1]
+ test "range (-ve)" when element -3 to -2 of tList is [1, true]
+ test "range (-ve, same)" when element -2 to -2 of tList is [true]
MCUnitTestHandlerThrows(TestRange_Zero, "range (zero)")
MCUnitTestHandlerThrows(TestRange_After, "range (after)")
@@ -219,40 +219,40 @@ public handler TestRange()
end handler
handler TestDeleteSingle_Zero()
- variable t
- put ["x", 1, true, []] into t
- delete element 0 of t
+ variable tList
+ put ["x", 1, true, []] into tList
+ delete element 0 of tList
end handler
handler TestDeleteSingle_Before()
- variable t
- put ["x", 1, true, []] into t
- delete element -5 of t
+ variable tList
+ put ["x", 1, true, []] into tList
+ delete element -5 of tList
end handler
handler TestDeleteSingle_After()
- variable t
- put ["x", 1, true, []] into t
- delete element 5 of t
+ variable tList
+ put ["x", 1, true, []] into tList
+ delete element 5 of tList
end handler
public handler TestDeleteSingle()
- variable t
+ variable tList
variable tTemplate
put ["x", 1, true, []] into tTemplate
- put tTemplate into t
- delete element 3 of t
- test "delete single (+ve)" when t is ["x", 1, []]
+ put tTemplate into tList
+ delete element 3 of tList
+ test "delete single (+ve)" when tList is ["x", 1, []]
- put tTemplate into t
- delete element -3 of t
- test "delete single (-ve)" when t is ["x", true, []]
+ put tTemplate into tList
+ delete element -3 of tList
+ test "delete single (-ve)" when tList is ["x", true, []]
- put tTemplate into t
- delete the first element of t
- test "delete first" when t is [1, true, []]
+ put tTemplate into tList
+ delete the first element of tList
+ test "delete first" when tList is [1, true, []]
- put tTemplate into t
- delete the last element of t
- test "delete last" when t is ["x", 1, true]
+ put tTemplate into tList
+ delete the last element of tList
+ test "delete last" when tList is ["x", 1, true]
MCUnitTestHandlerThrows(TestDeleteSingle_Zero, "delete single (zero)")
MCUnitTestHandlerThrows(TestDeleteSingle_Before, "delete single (before)")
@@ -260,32 +260,32 @@ public handler TestDeleteSingle()
end handler
handler TestDeleteRange_Zero()
- variable t
- put ["x", 1, true, []] into t
- delete element 0 to 0 of t
+ variable tList
+ put ["x", 1, true, []] into tList
+ delete element 0 to 0 of tList
end handler
handler TestDeleteRange_Before()
- variable t
- put ["x", 1, true, []] into t
- delete element -5 to -4 of t
+ variable tList
+ put ["x", 1, true, []] into tList
+ delete element -5 to -4 of tList
end handler
handler TestDeleteRange_After()
- variable t
- put ["x", 1, true, []] into t
- delete element 4 to 5 of t
+ variable tList
+ put ["x", 1, true, []] into tList
+ delete element 4 to 5 of tList
end handler
public handler TestDeleteRange()
- variable t
+ variable tList
variable tTemplate
put ["x", 1, true, []] into tTemplate
- put tTemplate into t
- delete element 2 to 3 of t
- test "delete range (+ve)" when t is ["x", []]
+ put tTemplate into tList
+ delete element 2 to 3 of tList
+ test "delete range (+ve)" when tList is ["x", []]
- put tTemplate into t
- delete element -3 to -2 of t
- test "delete range (-ve)" when t is ["x", []]
+ put tTemplate into tList
+ delete element -3 to -2 of tList
+ test "delete range (-ve)" when tList is ["x", []]
MCUnitTestHandlerThrows(TestDeleteRange_Zero, "delete range (zero)")
MCUnitTestHandlerThrows(TestDeleteRange_Before, "delete range (before)")
@@ -293,71 +293,71 @@ public handler TestDeleteRange()
end handler
public handler TestSplice()
- variable t
+ variable tList
variable tTemplate
put [1, 1, 1, 1] into tTemplate
- put tTemplate into t
- splice [2, 2] into element 2 to 3 of t
- test "splice (+ve)" when t is [1, 2, 2, 1]
+ put tTemplate into tList
+ splice [2, 2] into element 2 to 3 of tList
+ test "splice (+ve)" when tList is [1, 2, 2, 1]
- put tTemplate into t
- splice [2, 2] into element -3 to -2 of t
- test "splice (-ve)" when t is [1, 2, 2, 1]
+ put tTemplate into tList
+ splice [2, 2] into element -3 to -2 of tList
+ test "splice (-ve)" when tList is [1, 2, 2, 1]
- put tTemplate into t
- splice [2, 2] into element 2 to 2 of t
- test "splice (+ve, same)" when t is [1, 2, 2, 1, 1]
+ put tTemplate into tList
+ splice [2, 2] into element 2 to 2 of tList
+ test "splice (+ve, same)" when tList is [1, 2, 2, 1, 1]
- put tTemplate into t
- splice [2, 2] into element 2 of t
- test "splice (+ve, single)" when t is [1, 2, 2, 1, 1]
+ put tTemplate into tList
+ splice [2, 2] into element 2 of tList
+ test "splice (+ve, single)" when tList is [1, 2, 2, 1, 1]
- put tTemplate into t
- splice the empty list into element 1 to 4 of t
- test "splice (+ve, empty)" when t is empty
+ put tTemplate into tList
+ splice the empty list into element 1 to 4 of tList
+ test "splice (+ve, empty)" when tList is empty
end handler
handler TestSpliceBefore_Zero()
- variable t
- put [1] into t
- splice t before element 0 of t
+ variable tList
+ put [1] into tList
+ splice tList before element 0 of tList
end handler
handler TestSpliceAfter_Limit()
- variable t
- put [1] into t
- splice t after element 2 of t
+ variable tList
+ put [1] into tList
+ splice tList after element 2 of tList
end handler
public handler TestSpliceBefore()
- variable t
+ variable tList
variable tTemplate
put [1, 1, 1, 1] into tTemplate
- put tTemplate into t
- splice [2, 2] before element 2 of t
- test "splice before" when t is [1, 2, 2, 1, 1, 1]
+ put tTemplate into tList
+ splice [2, 2] before element 2 of tList
+ test "splice before" when tList is [1, 2, 2, 1, 1, 1]
- put tTemplate into t
- splice the empty list before element 2 of t
- test "splice before (empty)" when t is tTemplate
+ put tTemplate into tList
+ splice the empty list before element 2 of tList
+ test "splice before (empty)" when tList is tTemplate
MCUnitTestHandlerThrows(TestSpliceBefore_Zero, "splice before (zero)")
end handler
public handler TestSpliceAfter()
- variable t
+ variable tList
variable tTemplate
put [1, 1, 1, 1] into tTemplate
- put tTemplate into t
- splice [2, 2] after element 2 of t
- test "splice after" when t is [1, 1, 2, 2, 1, 1]
+ put tTemplate into tList
+ splice [2, 2] after element 2 of tList
+ test "splice after" when tList is [1, 1, 2, 2, 1, 1]
- put tTemplate into t
- splice the empty list after element 2 of t
- test "splice after (empty)" when t is tTemplate
+ put tTemplate into tList
+ splice the empty list after element 2 of tList
+ test "splice after (empty)" when tList is tTemplate
MCUnitTestHandlerThrows(TestSpliceAfter_Limit, "splice after (limit)")
end handler
@@ -381,15 +381,15 @@ end handler
----------------------------------------------------------------
public handler TestIndex()
- variable t
- put ["x", 1, true, [], []] into t
+ variable tList
+ put ["x", 1, true, [], []] into tList
- test "index" when the index of 1 in t is 2
- test "index (list)" when the index of [] in t is 4
- test "index (missing)" when the index of false in t is 0
+ test "index" when the index of 1 in tList is 2
+ test "index (list)" when the index of [] in tList is 4
+ test "index (missing)" when the index of false in tList is 0
- test "first index" when the first index of [] in t is 4
- test "last index" when the last index of [] in t is 5
+ test "first index" when the first index of [] in tList is 4
+ test "last index" when the last index of [] in tList is 5
test "index (empty)" when the index of 1 in [] is 0
end handler
@@ -550,18 +550,18 @@ end handler
----------------------------------------------------------------
public handler TestOffset()
- variable t
- put ["x", 1, true, [], []] into t
+ variable tList
+ put ["x", 1, true, [], []] into tList
- test "offset" when the offset of [1, true] in t is 2
- test "offset (missing)" when the offset of [true, 1] in t is 0
- test "offset (missing, overlap start)" when the offset of [false, "x"] in t is 0
- test "offset (missing, overlap end)" when the offset of [[], [], false] in t is 0
+ test "offset" when the offset of [1, true] in tList is 2
+ test "offset (missing)" when the offset of [true, 1] in tList is 0
+ test "offset (missing, overlap start)" when the offset of [false, "x"] in tList is 0
+ test "offset (missing, overlap end)" when the offset of [[], [], false] in tList is 0
- test "first offset" when the first offset of [[]] in t is 4
- test "last offset" when the last offset of [[]] in t is 5
+ test "first offset" when the first offset of [[]] in tList is 4
+ test "last offset" when the last offset of [[]] in tList is 5
- test "offset (empty)" when the offset of [] in t is 0
+ test "offset (empty)" when the offset of [] in tList is 0
end handler
----------------------------------------------------------------
diff --git a/tests/lcb/stdlib/string.lcb b/tests/lcb/stdlib/string.lcb
index 0e5518b52b2..d32762e11a4 100644
--- a/tests/lcb/stdlib/string.lcb
+++ b/tests/lcb/stdlib/string.lcb
@@ -20,37 +20,37 @@ module com.livecode.string.tests
use com.livecode.string
public handler TestPutBefore()
- variable t
- put "y" into t
- put "x" before t
- test "put before" when t is "xy"
+ variable tString
+ put "y" into tString
+ put "x" before tString
+ test "put before" when tString is "xy"
end handler
public handler TestPutAfter()
- variable t
- put "x" into t
- put "y" after t
- test "put after" when t is "xy"
+ variable tString
+ put "x" into tString
+ put "y" after tString
+ test "put after" when tString is "xy"
end handler
public handler TestReplace()
- variable t
+ variable tString
- put "x.x" into t
- replace "." with "x" in t
- test "replace (single instance)" when t is "xxx"
+ put "x.x" into tString
+ replace "." with "x" in tString
+ test "replace (single instance)" when tString is "xxx"
- put "..." into t
- replace "." with "x" in t
- test "replace (multiple instance)" when t is "xxx"
+ put "..." into tString
+ replace "." with "x" in tString
+ test "replace (multiple instance)" when tString is "xxx"
- put ".xx" into t
- replace ".x" with "x" in t
- test "replace (multichar)" when t is "xx"
+ put ".xx" into tString
+ replace ".x" with "x" in tString
+ test "replace (multichar)" when tString is "xx"
- put ".xx" into t
- replace ".x" with "." in t
- test "replace (multichar non-recursing)" when t is ".x"
+ put ".xx" into tString
+ replace ".x" with "." in tString
+ test "replace (multichar non-recursing)" when tString is ".x"
end handler
public handler TestConcat()
diff --git a/tests/lcb/stdlib/type.lcb b/tests/lcb/stdlib/type.lcb
index f687d756e9d..f51a462ca3b 100644
--- a/tests/lcb/stdlib/type.lcb
+++ b/tests/lcb/stdlib/type.lcb
@@ -18,12 +18,12 @@ along with LiveCode. If not see . */
module com.livecode.type.tests
public handler TestDefined()
- variable t as optional Boolean
+ variable tBool as optional Boolean
- test "is undefined" when t is undefined
- test "is not defined" when t is not defined
- test "is defined" when not (t is defined)
- test "is not undefined" when not (t is not undefined)
+ test "is undefined" when tBool is undefined
+ test "is not defined" when tBool is not defined
+ test "is defined" when not (tBool is defined)
+ test "is not undefined" when not (tBool is not undefined)
end handler
end module
diff --git a/tests/lcb/vm/dynamic-call.lcb b/tests/lcb/vm/dynamic-call.lcb
index 335a8631200..e8dbb49ebc1 100644
--- a/tests/lcb/vm/dynamic-call.lcb
+++ b/tests/lcb/vm/dynamic-call.lcb
@@ -6,14 +6,14 @@ handler Yes()
return true
end handler
-handler InvokeArgument(in f as Thunk)
- return f()
+handler InvokeArgument(in pFunc as Thunk)
+ return pFunc()
end handler
public handler TestDynamicInvokeVariable()
- variable f as Thunk
- put Yes into f
- test "dynamic invoke (variable)" when f()
+ variable pFunc as Thunk
+ put Yes into pFunc
+ test "dynamic invoke (variable)" when pFunc()
end handler
public handler TestDynamicInvokeArgument()
diff --git a/toolchain/Makefile b/toolchain/Makefile
index 8829c39da4e..c21c11e3a1f 100644
--- a/toolchain/Makefile
+++ b/toolchain/Makefile
@@ -319,7 +319,8 @@ $(COMPILE_stagedir)/stamp-gentle: $(COMPILE_gentle_inputs)
@cd $(COMPILE_srcdir) && \
for gfile in $(subst $(COMPILE_srcdir),.,$(COMPILE_gentle_inputs)); do \
gbase=`basename $$gfile` && \
- if [ ! -f $(COMPILE_stagesubdir)/$$gbase ]; then \
+ if [ ! -f $(COMPILE_stagesubdir)/$$gbase ] || \
+ [ $$gfile -nt $(COMPILE_stagesubdir)/$$gbase ]; then \
echo "cp $$gfile $(COMPILE_stagesubdir)" $(_PRINT_RULE); \
cp $$gfile $(COMPILE_stagesubdir) || exit $$? ; \
fi; \
diff --git a/toolchain/lc-compile/src/check.g b/toolchain/lc-compile/src/check.g
index cd8f888628b..9d179052a80 100644
--- a/toolchain/lc-compile/src/check.g
+++ b/toolchain/lc-compile/src/check.g
@@ -41,6 +41,9 @@
-- Check the syntax definitions are all correct.
CheckSyntaxDefinitions(Module)
+ -- Check that suitable identifiers are used in definitions
+ CheckIdentifiers(Module)
+
--------------------------------------------------------------------------------
-- At this point all identifiers either have a defined meaning, or are defined
@@ -492,6 +495,8 @@
-- Check method conformance for the class.
/* S7 */ CheckSyntaxMethods(Class, Methods)
+ -- Check keywords have appropriate form
+ CheckSyntaxKeywords(Syntax)
-- Mark variables can only be defined once for each possible path through a
-- syntax rule. For example:
@@ -1065,6 +1070,24 @@
----------
+'sweep' CheckSyntaxKeywords(ANY)
+
+ 'rule' CheckSyntaxKeywords(SYNTAX'keyword(Position, Value)):
+ (|
+ IsStringSuitableForKeyword(Value)
+ ||
+ Error_UnsuitableStringForKeyword(Position, Value)
+ |)
+
+ 'rule' CheckSyntaxKeywords(SYNTAX'unreservedkeyword(Position, Value)):
+ (|
+ IsStringSuitableForKeyword(Value)
+ ||
+ Error_UnsuitableStringForKeyword(Position, Value)
+ |)
+
+----------
+
'action' ComputeLModeOfSyntaxMethodArguments(PARAMETERLIST, SYNTAXCONSTANTLIST)
'rule' ComputeLModeOfSyntaxMethodArguments(parameterlist(parameter(_, Mode, _, _), ParamRest), constantlist(Arg, ArgRest)):
@@ -1594,6 +1617,83 @@
--------------------------------------------------------------------------------
+-- Emit warnings if there are any potential problems with the
+-- identifiers that are declared in the module. In particular, warn
+-- if there are any possible ambiguities with syntax keywords.
+
+-- This sweep only covers the places where identifiers are defined.
+-- This prevents warnings from being emitted everywhere that an
+-- identifier is used. It also prevents warnings about identifiers
+-- defined in a different module, which the author of the current
+-- module might not be able to do anything about.
+
+'sweep' CheckIdentifiers(ANY)
+
+ 'rule' CheckIdentifiers(MODULE'module(_, _, Id, Imports, Definitions)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Imports)
+ CheckIdentifiers(Definitions)
+
+ --
+
+ 'rule' CheckIdentifiers(DEFINITION'type(_, _, Id, Type)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Type)
+
+ 'rule' CheckIdentifiers(DEFINITION'constant(_, _, Id, Value)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Value)
+
+ 'rule' CheckIdentifiers(DEFINITION'variable(_, _, Id, _)):
+ CheckIdIsSuitableForDefinition(Id)
+
+ 'rule' CheckIdentifiers(DEFINITION'contextvariable(_, _, Id, Type, _)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Type)
+
+ 'rule' CheckIdentifiers(DEFINITION'handler(_, _, Id, _, Signature, Definitions, Body)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Signature)
+ CheckIdentifiers(Definitions)
+ CheckIdentifiers(Body)
+
+ 'rule' CheckIdentifiers(DEFINITION'foreignhandler(_, _, Id, Signature, _)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Signature)
+
+ 'rule' CheckIdentifiers(DEFINITION'property(_, _, Id, _, _)):
+ CheckIdIsSuitableForDefinition(Id)
+
+ 'rule' CheckIdentifiers(DEFINITION'event(_, _, Id, Signature)):
+ CheckIdIsSuitableForDefinition(Id)
+ CheckIdentifiers(Signature)
+
+ 'rule' CheckIdentifiers(DEFINITION'syntax(_, _, Id, _, _, _)):
+ CheckIdIsSuitableForDefinition(Id)
+
+ --
+
+ 'rule' CheckIdentifiers(PARAMETER'parameter(_, _, Id, _)):
+ CheckIdIsSuitableForDefinition(Id)
+
+ --
+
+ 'rule' CheckIdentifiers(STATEMENT'variable(_, Id, _)):
+ CheckIdIsSuitableForDefinition(Id)
+
+'action' CheckIdIsSuitableForDefinition(ID)
+
+ 'rule' CheckIdIsSuitableForDefinition(Id):
+ Id'Name -> Name
+ Id'Position -> Position
+ (|
+ IsNameSuitableForDefinition(Name)
+ ||
+ Warning_UnsuitableNameForDefinition(Position, Name)
+ |)
+
+--------------------------------------------------------------------------------
+
'condition' QueryHandlerIdSignature(ID -> SIGNATURE)
'rule' QueryHandlerIdSignature(Id -> Signature)
diff --git a/toolchain/lc-compile/src/lc-run.cpp b/toolchain/lc-compile/src/lc-run.cpp
index 72372cd8b8b..e6579fa9fc9 100644
--- a/toolchain/lc-compile/src/lc-run.cpp
+++ b/toolchain/lc-compile/src/lc-run.cpp
@@ -36,6 +36,9 @@ enum {
kMCRunExitStatusUncaughtError = 126,
};
+/* Possible entry point handler names. The first is the default. */
+const char *kMCRunHandlerNames[] = { "Main", "main", nil };
+
struct MCRunConfiguration
{
MCStringRef m_filename;
@@ -421,6 +424,51 @@ MCRunListHandlers (MCScriptModuleRef p_module)
return true;
}
+static bool
+MCRunGetHandlerName (MCScriptModuleRef p_module,
+ MCNameRef p_config_name,
+ MCNameRef & r_name)
+{
+ MCNameRef t_main_name = nil;
+ if (!MCNameIsEmpty (p_config_name))
+ {
+ t_main_name = p_config_name;
+ }
+ else
+ {
+ MCAutoProperListRef t_handler_list; /* List of MCNameRef */
+
+ if (!MCScriptCopyHandlersOfModule (p_module, &t_handler_list))
+ return false;
+
+ for (size_t i = 0; nil != kMCRunHandlerNames[i]; ++i)
+ {
+ MCNameRef t_name = MCNAME(kMCRunHandlerNames[i]);
+
+ uindex_t t_ignored;
+ if (!MCProperListFirstIndexOfElement (*t_handler_list, t_name,
+ 0, t_ignored))
+ continue;
+
+ if (i > 0)
+ {
+ MCAutoStringRef t_message;
+ if (!MCStringFormat (&t_message, "WARNING: Deprecated default handler '%s' (use '-H %s')\n", kMCRunHandlerNames[i], kMCRunHandlerNames[i]))
+ return false;
+ MCRunPrintMessage (stderr, *t_message);
+ }
+
+ t_main_name = t_name;
+ break;
+ }
+
+ if (nil == t_main_name)
+ t_main_name = MCNAME(kMCRunHandlerNames[0]);
+ }
+
+ r_name = MCValueRetain (t_main_name);
+ return true;
+}
/* ----------------------------------------------------------------
* Main program
@@ -439,7 +487,7 @@ main (int argc,
/* Defaults */
MCRunConfiguration t_config;
t_config.m_filename = MCValueRetain (kMCEmptyString);
- t_config.m_handler = MCValueRetain (MCNAME("main"));
+ t_config.m_handler = MCValueRetain (kMCEmptyName);
t_config.m_list_handlers = false;
if (!MCProperListCreateMutable (t_config.m_load_filenames))
MCRunStartupError(MCSTR("Initialization"));
@@ -465,11 +513,15 @@ main (int argc,
}
else
{
+ MCNewAutoNameRef t_handler;
+ if (!MCRunGetHandlerName (*t_module, t_config.m_handler, &t_handler))
+ MCRunStartupError (MCSTR("Handler"));
+
if (!MCScriptCreateInstanceOfModule (*t_module, &t_instance))
MCRunStartupError(MCSTR("Create Instance"));
if (!MCScriptCallHandlerOfInstance(*t_instance,
- t_config.m_handler,
+ *t_handler,
NULL, 0,
&t_ignored_retval))
MCRunHandlerError();
diff --git a/toolchain/lc-compile/src/literal.c b/toolchain/lc-compile/src/literal.c
index 005b8989a02..c8a0351a22c 100755
--- a/toolchain/lc-compile/src/literal.c
+++ b/toolchain/lc-compile/src/literal.c
@@ -459,3 +459,63 @@ void DumpScopes(void)
}
////////////////////////////////////////////////////////////////////////////////
+
+/* Check that module names contain a '.' character. */
+int
+IsNameSuitableForModule (NameRef p_id)
+{
+ const char *t_id;
+ size_t i;
+
+ GetStringOfNameLiteral (p_id, &t_id);
+
+ for (i = 0; '\0' != t_id[i]; ++i)
+ {
+ if ('.' == t_id[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Check that defined names *don't* match [a-z]+ (because these names
+ * are reserved for syntax keywords) */
+int
+IsNameSuitableForDefinition (NameRef p_id)
+{
+ const char *t_id;
+ size_t i;
+
+ GetStringOfNameLiteral (p_id, &t_id);
+
+ for (i = 0; '\0' != t_id[i]; ++i)
+ {
+ /* If char is not in [a-z] then string is okay */
+ if (t_id[i] < 'a' || t_id[i] > 'z')
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Keywords mustn't conflict with valid identifiers. Ensure this by
+ * forbidding keywords from containing any of the characters
+ * [A-Z0-9_.] */
+int
+IsStringSuitableForKeyword (const char *p_keyword)
+{
+ size_t i;
+
+ for (i = 0; p_keyword[i] != '\0'; ++i)
+ {
+ if ((p_keyword[i] == '.') ||
+ (p_keyword[i] == '_') ||
+ (p_keyword[i] >= 'A' && p_keyword[i] <= 'Z') ||
+ (p_keyword[i] >= '0' && p_keyword[i] <= '9'))
+ return 0;
+ }
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/toolchain/lc-compile/src/report.c b/toolchain/lc-compile/src/report.c
index 7f60affc144..c05693977d5 100644
--- a/toolchain/lc-compile/src/report.c
+++ b/toolchain/lc-compile/src/report.c
@@ -153,6 +153,13 @@ static void _ErrorI(long p_position, const char *p_message, NameRef p_name)
_ErrorS(p_position, p_message, t_string);
}
+static void _WarningI(long p_position, const char *p_message, NameRef p_name)
+{
+ const char *t_string;
+ GetStringOfNameLiteral(p_name, &t_string);
+ _WarningS(p_position, p_message, t_string);
+}
+
#define DEFINE_ERROR(Name, Message) \
void Error_##Name(long p_position) { _Error(p_position, Message); }
@@ -237,8 +244,12 @@ DEFINE_ERROR(ConstantsMustBeSimple, "Constant definitions must be a literal expr
DEFINE_ERROR_I(HandlerNotSuitableForPropertyGetter, "'%s' has inappropriate signature to be a property getter")
DEFINE_ERROR_I(HandlerNotSuitableForPropertySetter, "'%s' has inappropriate signature to be a property setter")
+DEFINE_ERROR_S(UnsuitableStringForKeyword, "Keyword '%s' is ambiguous with identifiers")
+
#define DEFINE_WARNING(Name, Message) \
void Warning_##Name(long p_position) { _Warning(p_position, Message); }
+#define DEFINE_WARNING_I(Name, Message) \
+ void Warning_##Name(long p_position, NameRef p_id) { _WarningI(p_position, Message, p_id); }
#define DEFINE_WARNING_S(Name, Message) \
void Warning_##Name(long p_position, const char *p_string) { _WarningS(p_position, Message, p_string); }
@@ -246,6 +257,7 @@ DEFINE_WARNING(MetadataClausesShouldComeAfterUseClauses, "Metadata clauses shoul
DEFINE_WARNING(EmptyUnicodeEscape, "Unicode escape sequence specified with no nibbles")
DEFINE_WARNING(UnicodeEscapeTooBig, "Unicode escape sequence too big, replaced with U+FFFD");
DEFINE_WARNING_S(DeprecatedTypeName, "Deprecated type name: use '%s'")
+DEFINE_WARNING_I(UnsuitableNameForDefinition, "All-lowercase name '%s' may cause future syntax error")
////////////////////////////////////////////////////////////////////////////////
diff --git a/toolchain/lc-compile/src/support.g b/toolchain/lc-compile/src/support.g
index 6d5c4e2ae4c..38a10b225ef 100644
--- a/toolchain/lc-compile/src/support.g
+++ b/toolchain/lc-compile/src/support.g
@@ -43,6 +43,9 @@
IsNameEqualToString
IsStringEqualToString
+ IsNameSuitableForDefinition
+ IsStringSuitableForKeyword
+
InitializeScopes
FinalizeScopes
DumpScopes
@@ -293,8 +296,10 @@
Error_NonHandlerTypeVariablesCannotBeCalled
Error_HandlerNotSuitableForPropertyGetter
Error_HandlerNotSuitableForPropertySetter
+ Error_UnsuitableStringForKeyword
Warning_MetadataClausesShouldComeAfterUseClauses
Warning_DeprecatedTypeName
+ Warning_UnsuitableNameForDefinition
--------------------------------------------------------------------------------
@@ -334,6 +339,9 @@
'condition' IsNameEqualToString(NAME, STRING)
'condition' IsStringEqualToString(STRING, STRING)
+'condition' IsNameSuitableForDefinition(NAME)
+'condition' IsStringSuitableForKeyword(STRING)
+
--------------------------------------------------------------------------------
'action' ReorderOperatorExpression(Sentinal: INT)
@@ -642,7 +650,10 @@
'action' Error_HandlerNotSuitableForPropertyGetter(Position: POS, Identifier: NAME)
'action' Error_HandlerNotSuitableForPropertySetter(Position: POS, Identifier: NAME)
+'action' Error_UnsuitableStringForKeyword(Position: POS, Token: STRING)
+
'action' Warning_MetadataClausesShouldComeAfterUseClauses(Position: POS)
'action' Warning_DeprecatedTypeName(Position: POS, NewType: STRING)
+'action' Warning_UnsuitableNameForDefinition(Position: POS, Identifier: NAME)
--------------------------------------------------------------------------------