test/bad.sod: Test error reporting and recovery.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 10 Aug 2019 13:48:07 +0000 (14:48 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 10 Aug 2019 14:45:45 +0000 (15:45 +0100)
Huh, what do you know?  That `demo' item has come back again.

test/Makefile.am
test/bad.ref [new file with mode: 0644]
test/bad.sod [new file with mode: 0644]

index 3ffec2b..8145746 100644 (file)
@@ -48,6 +48,16 @@ TESTS                        += test
 check_PROGRAMS         += test
 -include test.c-dep test.h-dep
 
+bad.out: bad.sod $(SOD)
+       $(SOD) -tc $(srcdir)/bad.sod >bad.raw-out 2>bad.raw-err; rc=$$?; \
+       { sed 's/^/| /' bad.raw-out; \
+         sed 's/^/* /; s,$(srcdir)/,test/,' bad.raw-err; \
+         echo "; rc = $$rc"; } >$@.new && \
+               mv $@.new $@
+check-local:: bad.out
+       diff -u $(srcdir)/bad.ref bad.out
+CLEANFILES             += bad.raw-out bad.raw-err bad.out
+
 EXTRA_DIST             += test.sod
 nodist_test_SOURCES     = test.c test.h
 BUILT_SOURCES          += $(nodist_test_SOURCES)
diff --git a/test/bad.ref b/test/bad.ref
new file mode 100644 (file)
index 0000000..f5d0c6b
--- /dev/null
@@ -0,0 +1,59 @@
+| ;; Hello from Lisp!
+| ;; DEMO "foo"
+* test/bad.sod:31:13: syntax error: Expected `{' but found `('
+* test/bad.sod:31:29: lexical error: Empty character literal
+* test/bad.sod:31:32: lexical error: Too many characters in character literal
+* test/bad.sod:33:6: syntax error: Expected <identifier> but found `{'
+* test/bad.sod:33:6: syntax error: Expected `:' but found `{'
+* test/bad.sod:36:12: syntax error: Expected `:' but found `{'
+* test/bad.sod:43:17: error: Slot declarations cannot have function type
+* test/bad.sod:43:19: syntax error: Expected <identifier> but found `.'
+* test/bad.sod:45:2: error: No message in class `Wrong' with name `fizzbuzz'
+* test/bad.sod:45:12: error: No superclass of `Wrong' with nickname `wtf'
+* test/bad.sod:45:26: error: No instance slot in class `Wrong' with name `z'
+* test/bad.sod:45:30: syntax error: Expected <identifier> but found `='
+* test/bad.sod:45:33: error: No superclass of `Wrong' with nickname `x'
+* test/bad.sod:46:29: syntax error: Expected `;' but found `{'
+* test/bad.sod:46:29: syntax error: Expected `}' but found `{'
+* test/bad.sod:41:13: error: Duplicate initializer for instance slot `int wrong.x' in class `Wrong'
+* test/bad.sod:40:11: note: Previous definition was here
+* test/bad.sod:42:13: error: Duplicate initializer for instance slot `int wrong.x' in class `Wrong'
+* test/bad.sod:40:11: note: Previous definition was here
+* test/bad.sod:40:2: error: Duplicate primary direct method for message `void wrong.frob(void)' in classs `Wrong'
+* test/bad.sod:38:2: note: Previous definition was here
+* test/bad.sod:46:29: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `{'
+* test/bad.sod:46:49: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `}'
+* test/bad.sod:47:0: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `}'
+* test/bad.sod:52:30: error: Type mismatch for keyword argument `x' in methods for message `void fail.badkw(?int x)' applicable to class `Arrgh'
+* test/bad.sod:54:2: note: Type `double' declared in primary direct method of `Arrgh' (defined here)
+* test/bad.sod:49:43: note: Type `int' declared in message definition in `Fail' (here)
+* test/bad.sod:50:21: note: Class `Fail' is a direct superclass of `Unlikely', defined here
+* test/bad.sod:52:30: note: Class `Unlikely' is a direct superclass of `Arrgh', defined here
+* test/bad.sod:52:30: error: Type mismatch for keyword argument `y' in methods for message `void fail.badkw(?int x)' applicable to class `Arrgh'
+* test/bad.sod:51:53: note: Type `int' declared in primary direct method of `Whoops' (defined here)
+* test/bad.sod:52:30: note: Class `Whoops' is a direct superclass of `Arrgh', defined here
+* test/bad.sod:50:58: note: Type `double' declared in primary direct method of `Unlikely' (defined here)
+* test/bad.sod:60:41: error: Duplicate nickname `sub' in superclasses of `BadNicks': used by `RSub' and `LSub'
+* test/bad.sod:60:41: note: Class `RSub' is a direct superclass of `BadNicks', defined here
+* test/bad.sod:60:41: note: Class `LSub' is a direct superclass of `BadNicks', defined here
+* test/bad.sod:60:41: error: Duplicate nickname `join' in superclasses of `BadNicks': used by `JSuper' and `BadNicks'
+* test/bad.sod:58:32: note: Class `JSuper' is a direct superclass of `LSub', defined here
+* test/bad.sod:66:37: error: Ill-formed superclass graph: can't construct class precedence list for `Splinch'
+* test/bad.sod:66:37: note: Class `Splinch' orders `SodObject' before `Nioj'
+* test/bad.sod:64:24: note: Class `Join' orders `Left' before `SodObject'
+* test/bad.sod:66:37: note: Class `Join' is a direct superclass of `Splinch', defined here
+* test/bad.sod:65:24: note: Class `Nioj' orders `Nioj' before `Left' and `SodObject'
+* test/bad.sod:66:37: note: Class `Nioj' is a direct superclass of `Splinch', defined here
+* test/bad.sod:67:37: error: Class `Wrong' is incomplete
+* test/bad.sod:67:37: error: In `Hopeless', chain-to class `Super' is not a proper superclass
+* test/bad.sod:83:46: error: No obvious choice for implicit metaclass: candidates are `MyClass' and `MyOtherClass'
+* test/bad.sod:78:26: note: Direct superclass `MyObject' defined here has metaclass `MyClass'
+* test/bad.sod:82:58: note: Direct superclass `MyOtherObject' defined here has metaclass `MyOtherClass'
+* test/bad.sod:83:46: error: Metaclass `MyClass' of `WhichMetaClass' isn't a subclass of `MyOtherClass'
+* test/bad.sod:82:58: note: Direct superclass `MyOtherObject' defined here has metaclass `MyOtherClass'
+* test/bad.sod:88:0: error: Class `dismissed' is incomplete
+* test/bad.sod:88:0: syntax error: Expected `{' but found `;'
+* test/bad.sod:88:0: syntax error: Expected `}' but found `;'
+* test/bad.sod:88:0: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `;'
+* sod: Finished with 34 errors
+; rc = 2
diff --git a/test/bad.sod b/test/bad.sod
new file mode 100644 (file)
index 0000000..4ca273e
--- /dev/null
@@ -0,0 +1,88 @@
+/* -*-sod-*-
+ *
+ * A file full of terribleness, to check error reporting and recovery.
+ *
+ * (c) 2019 Straylight/Edgeware
+ */
+
+/* The reference file for this test isn't intended to be normative: it's fine
+ * if things are reordered, or messages are rephrased.  But it's good to know
+ * when these things change, and besides this approach is way easier than the
+ * alternatives.
+ */
+
+typename Bad;
+
+import "chimaera";
+
+lisp ;this is actually a comment
+  (format t ";; Hello from Lisp!~%")
+  /* and this is the statement terminator */;
+
+lisp
+(define-pluggable-parser module test (scanner pset)
+  ;; `demo' string `;'
+  (declare (ignore pset))
+  (with-parser-context (token-scanner-context :scanner scanner)
+    (parse (seq ("demo" (string (must :string)) (nil (must #\;)))
+            (format t ";; DEMO ~S~%" string)))));
+demo "foo";
+
+code c: user ( not like this '' 'xyz' );
+
+class {
+}
+
+class Wrong {
+  void frob() { ... }
+  void wrong.frob() { ... }
+
+  int x = 2;
+  wrong.x = 7;
+  wrong.x = 3;
+  int filler, y(), .z[45], q;
+  int wrong.fizzbuzz(int n) extern;
+  wtf.y = 19, wrong.z = 69, x.= r;
+  int (*bogon)(const char *) { return strlen(p); }
+}
+
+class Fail: SodObject { void badkw(?int x) extern; void ebw(?) extern; }
+class Unlikely: Fail { void fail.badkw(?double y) extern; }
+class Whoops: Fail { void fail.badkw(?int y) extern; }
+class Arrgh: Unlikely, Whoops {
+  void fail.badkw(?double x) extern;
+  void fail.ebw(?) extern;
+}
+
+[nick = join] class JSuper: SodObject { }
+[nick = sub] class LSub: JSuper { }
+[nick = sub] class RSub: JSuper { }
+[nick = join] class BadNicks: LSub, RSub { }
+class Super: SodObject { }
+class Left: Super { }
+class Right: Super { }
+class Join: Left, Right { }
+class Nioj: Right, Left { }
+class Splinch: Join, SodObject, Nioj { }
+[link = Super] class Hopeless: Wrong { }
+
+[link = SodClass]
+class MyClass: SodClass {
+  int foo = 1;
+  int bar = 2;
+}
+
+class MyOtherClass: SodClass { }
+
+[metaclass = MyClass, link = SodObject]
+class MyObject: SodObject {
+  class myclass.foo = 42;
+}
+
+[metaclass = MyOtherClass] class MyOtherObject: SodObject { }
+class WhichMetaClass: MyObject, MyOtherObject { }
+
+class dismissed;
+
+class hopeful: dismissed
+;