From 7edca9823ec8ef0aed10c88fa07ef969792aab77 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 19 Oct 2026 14:56:14 -0700 Subject: Split from ch25, SCCP and interprocedural SCCP --- .../java/com/seaofnodes/simple/LiteralTest.java | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 chapter-sccp/src/test/java/com/seaofnodes/simple/LiteralTest.java (limited to 'chapter-sccp/src/test/java/com/seaofnodes/simple/LiteralTest.java') diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/LiteralTest.java b/chapter-sccp/src/test/java/com/seaofnodes/simple/LiteralTest.java new file mode 100644 index 00000000..447ef46e --- /dev/null +++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/LiteralTest.java @@ -0,0 +1,65 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.type.TypeConAryB; +import com.seaofnodes.simple.type.TypeInteger; +import com.seaofnodes.simple.type.TypeMemPtr; +import org.junit.Test; +import static org.junit.Assert.*; + +public class LiteralTest { + private static final String[] ESCAPES = {"\\0", "\\n", "\\t", "\\r", "\\\\", "\\\"", "\\'"}; + private static final int[] VALUES = {0, 10, 9, 13, 92, 34, 39}; + + @Test public void testStringEscapes() { + for (int i = 0; i < ESCAPES.length; i++) + assertString(ESCAPES[i], new byte[]{(byte)VALUES[i]}); + assertString("a\\\"b\\\\c\\0d", new byte[]{97, 34, 98, 92, 99, 0, 100}); + assertString("", new byte[]{}); + assertString("plain", new byte[]{112, 108, 97, 105, 110}); + } + + private static void assertString(String text, byte[] expected) { + var code = new CodeGen("return \"" + text + "\";").driver(CodeGen.Phase.TypeCheck); + TypeMemPtr ptr = (TypeMemPtr)code.expr()._type; + TypeConAryB bytes = (TypeConAryB)ptr._obj.field("[]")._t; + assertArrayEquals(text, expected, bytes._ary); + } + + @Test public void testCharacterEscapes() { + for (int i = 0; i < ESCAPES.length; i++) + assertCharacter(ESCAPES[i], VALUES[i]); + assertCharacter("A", 65); + } + + private static void assertCharacter(String text, int expected) { + var code = new CodeGen("return '" + text + "';").driver(CodeGen.Phase.TypeCheck); + assertEquals(text, expected, ((TypeInteger)code.expr()._type).value()); + } + + @Test public void testMalformedStrings() { + assertBadLiteral("return \"\\q\";", "Unknown string escape"); + assertBadLiteral("return \"abc", "Unclosed string"); + assertBadLiteral("return \"abc\\", "Unclosed string"); + // The quote closes the string at EOF; the missing token is the semicolon. + assertBadLiteral("return \"plain\"", ";"); + } + + @Test public void testMalformedCharacters() { + assertBadLiteral("return '\\q';", "Unknown character escape"); + assertBadLiteral("return '", "Unclosed character"); + assertBadLiteral("return '\\", "Unclosed character"); + assertBadLiteral("return '';", "Syntax error"); + assertBadLiteral("return 'ab';", "Syntax error"); + assertBadLiteral("return 'a", "Syntax error"); + } + + private static void assertBadLiteral(String src, String message) { + try { + new CodeGen(src).parse(); + fail("Accepted malformed literal: " + src); + } catch (Parser.ParseException e) { + assertTrue(e.getMessage(), e.getMessage().contains(message)); + } + } +} -- cgit v1.2.3