This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,3 @@
(* A macro is defined twice. *)
#define FOO "oh"
#define FOO "no"

View file

@ -0,0 +1,2 @@
Error: File "already_defined.cppo", line 3, characters 0-17
Error: "FOO" is already defined

View file

@ -0,0 +1,3 @@
(* A parameterized macro is applied to no arguments. *)
#define FOO(x) x
FOO + 1

View file

@ -0,0 +1,2 @@
Error: File "applied_to_none.cppo", line 3, characters 0-3
Error: "FOO" expects 1 argument but is applied to 0 argument.

View file

@ -0,0 +1,3 @@
(* This test shows an arity mismatch error. *)
#define INCR(x) x+1
INCR(x, y)

View file

@ -0,0 +1,2 @@
Error: File "arity_mismatch.cppo", line 3, characters 0-10
Error: "INCR" expects 1 argument but is applied to 2 arguments.

View file

@ -0,0 +1,3 @@
#define ID(X) X
#define APPLY(F : [.], X) F (* intentionally forgetting to apply F *)
APPLY(ID, 42)

View file

@ -0,0 +1,2 @@
Error: File "arity_mismatch_indirect.cppo", line 2, characters 26-27
Error: "F" expects 1 argument but is applied to 0 argument.

View file

@ -0,0 +1,2 @@
(* A parameterized macro cannot have zero arguments. *)
#define FOO() "not ok"

View file

@ -0,0 +1,2 @@
Error: File "at_least_one_arg.cppo", line 2, characters 12-13
Error: A macro must have at least one formal parameter

View file

@ -0,0 +1,6 @@
#define EVENT(n,ty) external CONCAT(on,CAPITALIZE(n)) : ty = STRINGIFY(n) [@@bs.val]
EVENT(exit, unit -> unit)

View file

@ -0,0 +1,6 @@
# 6 "capital.cppo"
external onExit : unit -> unit = "exit" [@@bs.val]

View file

@ -0,0 +1,2 @@
#define FOO(x, (* a comment *) y) x+y
FOO(42, 23)

View file

@ -0,0 +1,2 @@
Error: File "comment_in_formals.cppo", line 1, characters 15-16
Error: Invalid formal parameter: expected an identifier

View file

@ -0,0 +1,7 @@
(* '"' *)
#define BE_GONE
(* "*)"
#define DONT_TOUCH_THIS
*)

View file

@ -0,0 +1,8 @@
# 1 "comments.cppo"
(* '"' *)
# 5 "comments.cppo"
(* "*)"
#define DONT_TOUCH_THIS
*)

View file

@ -0,0 +1,47 @@
#if 1 = 1
#else
#error "ignored #else (?)"
#endif
#if true
banana
#elif false
apple
#error "ignored #elif (?)"
#endif
#if false
earthworm
#error ""
#elif true
apricot
#endif
#if false
cuckoo
#error ""
#else
#if false
egg
#error ""
#else
nest
#endif
#endif
#define X 3
#if false
helicopter
#error ""
#elif false
ocean
#error ""
#else
#if X = 12
sand
#error ""
#elif 4 * X = 12
sea urchin
#endif
#endif

View file

@ -0,0 +1,17 @@
# 7 "cond.cppo"
banana
# 17 "cond.cppo"
apricot
# 28 "cond.cppo"
nest
# 45 "cond.cppo"
sea urchin

View file

@ -0,0 +1,88 @@
(* This macro application combinator provides call-by-value
semantics: the actual argument is evaluated up front and
its value is bound to a variable, which is passed as an
argument to the macro [F]. *)
#def APPLY(F : [.], X : .)
(let __x = (X) in F(__x))
(* Multiple lines permitted; no backslash required. *)
#enddef
(* Some trivial tests. *)
#define ID(X) X
#define C 42
let forty_one = APPLY(ID, 41)
let forty_two = APPLY(ID, C )
(* A [for]-loop macro. *)
#def LOOP(start, finish, body : [.])
(
for __index = start to finish-1 do
body(__index)
done
)
#enddef
(* A [for]-loop macro that performs unrolling. *)
#def UNROLLED_LOOP(start, finish, body : [.]) (
(* #define can be nested inside #def. *)
#define BODY(i) APPLY(body, i)
(* #def can be nested inside #def. *)
#def INCREMENT(i, k)
i := !i + k
#enddef
let __finish = (finish) in
let __index = ref (start) in
while !__index + 2 <= __finish do
BODY(!__index);
BODY(!__index + 1);
INCREMENT(__index, 2)
done;
while !__index < __finish do
BODY(!__index);
INCREMENT(__index, 1)
done
)
#enddef
(* In the examples that follow, #scope ... #endscope is used to
avoid the need to #undefine local macros such as BODY and F. *)
(* Iteration over an array, with a normal loop. *)
let iter f a =
#scope
#define BODY(i) (f a.(i))
LOOP(0, Array.length a, BODY)
#endscope
(* Iteration over an array, with an unrolled loop. *)
let unrolled_iter f a =
#scope
#define BODY(i) (f a.(i))
UNROLLED_LOOP(0, Array.length a, BODY)
#endscope
(* Printing an array, with a normal loop. *)
let print_int_array a =
#scope
#define F(i) Printf.printf "%d" a.(i)
LOOP(0, Array.length a, F)
#endscope
(* A higher-order macro that produces a definition of [iter],
and accepts an arbitrary definition of the macro [LOOP]. *)
#def DEFINE_ITER(iter, LOOP : [..[.]])
#scope
#define BODY(i) (f a.(i))
let iter f a =
LOOP(0, Array.length a, BODY)
#endscope
#enddef
(* Some noise, which does not affect the above definitions. *)
#define BODY(i) "noise"
DEFINE_ITER(iter, LOOP)
DEFINE_ITER(unrolled_iter, UNROLLED_LOOP)
(* Just because we can, undefine BODY. *)
#undef BODY

View file

@ -0,0 +1,152 @@
# 1 "def.cppo"
(* This macro application combinator provides call-by-value
semantics: the actual argument is evaluated up front and
its value is bound to a variable, which is passed as an
argument to the macro [F]. *)
# 10 "def.cppo"
(* Some trivial tests. *)
# 13 "def.cppo"
let forty_one =
# 13 "def.cppo"
(let __x = ( 41) in __x )
(* Multiple lines permitted; no backslash required. *)
# 14 "def.cppo"
let forty_two =
# 14 "def.cppo"
(let __x = ( 42 ) in __x )
(* Multiple lines permitted; no backslash required. *)
# 16 "def.cppo"
(* A [for]-loop macro. *)
# 25 "def.cppo"
(* A [for]-loop macro that performs unrolling. *)
# 47 "def.cppo"
(* In the examples that follow, #scope ... #endscope is used to
avoid the need to #undefine local macros such as BODY and F. *)
(* Iteration over an array, with a normal loop. *)
let iter f a =
# 54 "def.cppo"
(
for __index = 0 to Array.length a-1 do
(f a.(__index))
done
)
# 57 "def.cppo"
(* Iteration over an array, with an unrolled loop. *)
let unrolled_iter f a =
# 61 "def.cppo"
(
(* #define can be nested inside #def. *)
(* #def can be nested inside #def. *)
let __finish = ( Array.length a) in
let __index = ref (0) in
while !__index + 2 <= __finish do
(let __x = ( !__index) in (f a.(__x)) )
(* Multiple lines permitted; no backslash required. *)
;
(let __x = ( !__index + 1) in (f a.(__x)) )
(* Multiple lines permitted; no backslash required. *)
;
__index := !__index + 2
done;
while !__index < __finish do
(let __x = ( !__index) in (f a.(__x)) )
(* Multiple lines permitted; no backslash required. *)
;
__index := !__index + 1
done
)
# 64 "def.cppo"
(* Printing an array, with a normal loop. *)
let print_int_array a =
# 68 "def.cppo"
(
for __index = 0 to Array.length a-1 do
Printf.printf "%d" a.(__index)
done
)
# 71 "def.cppo"
(* A higher-order macro that produces a definition of [iter],
and accepts an arbitrary definition of the macro [LOOP]. *)
# 81 "def.cppo"
(* Some noise, which does not affect the above definitions. *)
# 84 "def.cppo"
let iter f a =
(
for __index = 0 to Array.length a-1 do
(f a.(__index))
done
)
# 85 "def.cppo"
let unrolled_iter f a =
(
(* #define can be nested inside #def. *)
(* #def can be nested inside #def. *)
let __finish = ( Array.length a) in
let __index = ref (0) in
while !__index + 2 <= __finish do
(let __x = ( !__index) in (f a.(__x)) )
(* Multiple lines permitted; no backslash required. *)
;
(let __x = ( !__index + 1) in (f a.(__x)) )
(* Multiple lines permitted; no backslash required. *)
;
__index := !__index + 2
done;
while !__index < __finish do
(let __x = ( !__index) in (f a.(__x)) )
(* Multiple lines permitted; no backslash required. *)
;
__index := !__index + 1
done
)
# 87 "def.cppo"
(* Just because we can, undefine BODY. *)

View file

@ -0,0 +1,2 @@
(* This #define is NOT ended by a new line, but is nevertheless accepted. *)
#define TWICE(e) e + e

View file

@ -0,0 +1,292 @@
;; ---------------------------------------------------------------------------
;; Positive tests.
(rule
(targets ext.out)
(deps
(:< ext.cppo)
source.sh)
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} -x "rot13:tr '[a-z]' '[n-za-m]'" -x
"source:sh source.sh '%F' %B %E" %{<}))))
(rule
(targets comments.out)
(deps
(:< comments.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets cond.out)
(deps
(:< cond.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets tuple.out)
(deps
(:< tuple.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets loc.out)
(deps
(:< loc.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets paren_arg.out)
(deps
(:< paren_arg.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets unmatched.out)
(deps
(:< unmatched.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets version.out)
(deps
(:< version.cppo))
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} -V X:123.05.2-alpha.1+foo-2.1 -V COQ:8.13+beta1 -V OCAML:4.12.0~alpha1 %{<}))))
(rule
(targets test.out)
(deps
(:< test.cppo)
incl.cppo
incl2.cppo)
(action
(with-stdout-to
%{targets}
(run %{bin:cppo} %{<}))))
(rule
(targets lexical.out)
(deps (:< lexical.cppo))
(action (with-stdout-to %{targets} (run %{bin:cppo} %{<}))))
(rule
(targets scope.out)
(deps (:< scope.cppo))
(action (with-stdout-to %{targets} (run %{bin:cppo} %{<}))))
(rule
(targets higher_order_macros.out)
(deps (:< higher_order_macros.cppo))
(action (with-stdout-to %{targets} (run %{bin:cppo} %{<}))))
(rule
(targets include_define_on_last_line.out)
(deps (:< include_define_on_last_line.cppo) define_on_last_line.cppo)
(action (with-stdout-to %{targets} (run %{bin:cppo} %{<}))))
(rule
(targets def.out)
(deps (:< def.cppo))
(action (with-stdout-to %{targets} (run %{bin:cppo} %{<}))))
(rule (alias runtest) (package cppo)
(action (diff ext.ref ext.out)))
(rule (alias runtest) (package cppo)
(action (diff comments.ref comments.out)))
(rule (alias runtest) (package cppo)
(action (diff cond.ref cond.out)))
(rule (alias runtest) (package cppo)
(action (diff tuple.ref tuple.out)))
(rule (alias runtest) (package cppo)
(action (diff loc.ref loc.out)))
(rule (alias runtest) (package cppo)
(action (diff paren_arg.ref paren_arg.out)))
(rule (alias runtest) (package cppo)
(action (diff version.ref version.out)))
(rule (alias runtest) (package cppo)
(action (diff unmatched.ref unmatched.out)))
(rule (alias runtest) (package cppo)
(action (diff test.ref test.out)))
(rule (alias runtest) (package cppo)
(action (diff lexical.ref lexical.out)))
(rule (alias runtest) (package cppo)
(action (diff scope.ref scope.out)))
(rule (alias runtest) (package cppo)
(action (diff higher_order_macros.ref higher_order_macros.out)))
(rule (alias runtest) (package cppo)
(action (diff include_define_on_last_line.ref include_define_on_last_line.out)))
(rule (alias runtest) (package cppo)
(action (diff def.ref def.out)))
;; ---------------------------------------------------------------------------
;; Negative tests.
(rule
(targets arity_mismatch.err)
(deps (:< arity_mismatch.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff arity_mismatch.ref arity_mismatch.err)))
(rule
(targets applied_to_none.err)
(deps (:< applied_to_none.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff applied_to_none.ref applied_to_none.err)))
(rule
(targets expects_no_args.err)
(deps (:< expects_no_args.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff expects_no_args.ref expects_no_args.err)))
(rule
(targets already_defined.err)
(deps (:< already_defined.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff already_defined.ref already_defined.err)))
(rule
(targets at_least_one_arg.err)
(deps (:< at_least_one_arg.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff at_least_one_arg.ref at_least_one_arg.err)))
(rule
(targets comment_in_formals.err)
(deps (:< comment_in_formals.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff comment_in_formals.ref comment_in_formals.err)))
(rule
(targets arity_mismatch_indirect.err)
(deps (:< arity_mismatch_indirect.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff arity_mismatch_indirect.ref arity_mismatch_indirect.err)))
(rule
(targets expect_ident.err)
(deps (:< expect_ident.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff expect_ident.ref expect_ident.err)))
(rule
(targets expect_ident_empty.err)
(deps (:< expect_ident_empty.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff expect_ident_empty.ref expect_ident_empty.err)))
(rule
(targets undefined.err)
(deps (:< undefined.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff undefined.ref undefined.err)))
(rule
(targets shape_mismatch.err)
(deps (:< shape_mismatch.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff shape_mismatch.ref shape_mismatch.err)))
(rule
(targets int_expansion_error.err)
(deps (:< int_expansion_error.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff int_expansion_error.ref int_expansion_error.err)))
(rule
(targets extraneous_enddef.err)
(deps (:< extraneous_enddef.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff extraneous_enddef.ref extraneous_enddef.err)))
(rule
(targets missing_enddef.err)
(deps (:< missing_enddef.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff missing_enddef.ref missing_enddef.err)))
(rule
(targets missing_endscope.err)
(deps (:< missing_endscope.cppo))
(action (with-stderr-to %{targets}
(with-accepted-exit-codes (not 0) (run %{bin:cppo} %{<})))))
(rule (alias runtest) (package cppo)
(action (diff missing_endscope.ref missing_endscope.err)))

View file

@ -0,0 +1,6 @@
let id x = x
#define ID(X) X
#define APPLY(F : [.], X) F(X)
APPLY(ID(id), 42)
(* invalid because APPLY expects a macro as an argument:
ID would be a valid argument; ID(id) is not. *)

View file

@ -0,0 +1,2 @@
Error: File "expect_ident.cppo", line 4, characters 6-12
Error: The name of a macro is expected in this position

View file

@ -0,0 +1,6 @@
let id x = x
#define ID(X) X
#define APPLY(F : [.], X) F(X)
APPLY(, 42)
(* invalid because APPLY expects a macro as an argument:
an empty argument is not allowed. *)

View file

@ -0,0 +1,2 @@
Error: File "expect_ident_empty.cppo", line 4, characters 6-6
Error: The name of a macro is expected in this position

View file

@ -0,0 +1,3 @@
(* A non-parameterized macro is given actual arguments. *)
#define FOO "foo"
1 + FOO(42)

View file

@ -0,0 +1,2 @@
Error: File "expects_no_args.cppo", line 3, characters 4-11
Error: "FOO" expects 0 argument but is applied to 1 argument.

View file

@ -0,0 +1,10 @@
hello
#ext rot13
abc
\#endext
def
#endext
goodbye
#ext source
#endext

View file

@ -0,0 +1,28 @@
# 1 "ext.cppo"
hello
nop
#raqrkg
qrs
# 7 "ext.cppo"
goodbye
# 9
(*
hello
#ext rot13
abc
\#endext
def
#endext
goodbye
#ext source
#endext
*)
(*
Environment variables:
CPPO_FILE=ext.cppo
CPPO_FIRST_LINE=9
CPPO_LAST_LINE=11
*)
# 11

View file

@ -0,0 +1,4 @@
#define FOO \
42
(* The following #enddef is extraneous; it should not be there. *)
#enddef

View file

@ -0,0 +1,2 @@
Error: File "extraneous_enddef.cppo", line 4, characters 0-8
Error: syntax error

View file

@ -0,0 +1,69 @@
(* This macro application combinator provides call-by-value
semantics: the actual argument is evaluated up front and
its value is bound to a variable, which is passed as an
argument to the macro [F]. *)
#define APPLY(F : [.], X : .)(let __x = (X) in F(__x))
(* Some trivial tests. *)
#define ID(X) X
#define C 42
let forty_one = APPLY(ID, 41)
let forty_two = APPLY(ID, C )
(* A [for]-loop macro. *)
#define LOOP(start, finish, body : [.]) (\
for __index = start to finish-1 do\
body(__index)\
done\
)
(* A [for]-loop macro that performs unrolling. *)
#define UNROLLED_LOOP(start, finish, body : [.]) (\
let __finish = (finish) in\
let __index = ref (start) in\
while !__index + 2 <= __finish do\
APPLY(body, !__index);\
APPLY(body, !__index + 1);\
__index := !__index + 2\
done;\
while !__index < __finish do\
APPLY(body, !__index);\
__index := !__index + 1\
done\
)
(* In some of the examples that follow, #scope ... #endscope is used
to avoid the need to #undefine local macros such as BODY and F. *)
(* Iteration over an array, with a normal loop. *)
let iter f a =
#scope
#define BODY(i) (f a.(i))
LOOP(0, Array.length a, BODY)
#endscope
(* Iteration over an array, with an unrolled loop. *)
let unrolled_iter f a =
#scope
#define BODY(i) (f a.(i))
UNROLLED_LOOP(0, Array.length a, BODY)
#endscope
(* Printing an array, with a normal loop. *)
let print_int_array a =
#define F(i) Printf.printf "%d" a.(i)
LOOP(0, Array.length a, F)
(* A higher-order macro that produces a definition of [iter],
and accepts an arbitrary definition of the macro [LOOP]. *)
#define BODY(i) (f a.(i))
#define DEFINE_ITER(iter, LOOP : [..[.]]) \
let iter f a = \
LOOP(0, Array.length a, BODY)
#undef BODY
(* Some noise, which does not affect the above definitions. *)
#define BODY(i) "noise"
DEFINE_ITER(iter, LOOP)
DEFINE_ITER(unrolled_iter, UNROLLED_LOOP)

View file

@ -0,0 +1,100 @@
# 1 "higher_order_macros.cppo"
(* This macro application combinator provides call-by-value
semantics: the actual argument is evaluated up front and
its value is bound to a variable, which is passed as an
argument to the macro [F]. *)
# 7 "higher_order_macros.cppo"
(* Some trivial tests. *)
# 10 "higher_order_macros.cppo"
let forty_one =
# 10 "higher_order_macros.cppo"
(let __x = ( 41) in __x )
# 11 "higher_order_macros.cppo"
let forty_two =
# 11 "higher_order_macros.cppo"
(let __x = ( 42 ) in __x )
# 13 "higher_order_macros.cppo"
(* A [for]-loop macro. *)
# 20 "higher_order_macros.cppo"
(* A [for]-loop macro that performs unrolling. *)
# 35 "higher_order_macros.cppo"
(* In some of the examples that follow, #scope ... #endscope is used
to avoid the need to #undefine local macros such as BODY and F. *)
(* Iteration over an array, with a normal loop. *)
let iter f a =
# 42 "higher_order_macros.cppo"
(
for __index = 0 to Array.length a-1 do
(f a.(__index))
done
)
# 45 "higher_order_macros.cppo"
(* Iteration over an array, with an unrolled loop. *)
let unrolled_iter f a =
# 49 "higher_order_macros.cppo"
(
let __finish = ( Array.length a) in
let __index = ref (0) in
while !__index + 2 <= __finish do
(let __x = ( !__index) in (f a.(__x)) ) ;
(let __x = ( !__index + 1) in (f a.(__x)) ) ;
__index := !__index + 2
done;
while !__index < __finish do
(let __x = ( !__index) in (f a.(__x)) ) ;
__index := !__index + 1
done
)
# 52 "higher_order_macros.cppo"
(* Printing an array, with a normal loop. *)
let print_int_array a =
# 55 "higher_order_macros.cppo"
(
for __index = 0 to Array.length a-1 do
Printf.printf "%d" a.(__index)
done
)
# 57 "higher_order_macros.cppo"
(* A higher-order macro that produces a definition of [iter],
and accepts an arbitrary definition of the macro [LOOP]. *)
# 65 "higher_order_macros.cppo"
(* Some noise, which does not affect the above definitions. *)
# 68 "higher_order_macros.cppo"
let iter f a =
(
for __index = 0 to Array.length a-1 do
(f a.(__index))
done
)
# 69 "higher_order_macros.cppo"
let unrolled_iter f a =
(
let __finish = ( Array.length a) in
let __index = ref (0) in
while !__index + 2 <= __finish do
(let __x = ( !__index) in (f a.(__x)) ) ;
(let __x = ( !__index + 1) in (f a.(__x)) ) ;
__index := !__index + 2
done;
while !__index < __finish do
(let __x = ( !__index) in (f a.(__x)) ) ;
__index := !__index + 1
done
)

View file

@ -0,0 +1,3 @@
included
#include "incl2.cppo"

View file

@ -0,0 +1 @@
ok

View file

@ -0,0 +1,3 @@
#include "define_on_last_line.cppo"
(* Check that the definition of TWICE has been accepted: *)
let f x = TWICE(x)

View file

@ -0,0 +1,7 @@
# 1 "define_on_last_line.cppo"
(* This #define is NOT ended by a new line, but is nevertheless accepted. *)
# 2 "include_define_on_last_line.cppo"
(* Check that the definition of TWICE has been accepted: *)
let f x =
# 3 "include_define_on_last_line.cppo"
x + x

View file

@ -0,0 +1,4 @@
#define FOO 3+3
#if FOO = 0
let x = "Hello"
#endif

View file

@ -0,0 +1,4 @@
Error: File "int_expansion_error.cppo", line 2, characters 4-7
Error: Variable FOO found in cppo boolean expression must expand
into an int literal, into a tuple of int literals,
or into a variable with the same properties.

View file

@ -0,0 +1,27 @@
(* This test shows that the definition of BAR captures the original
definition of FOO, so even if FOO is redefined, the expansion of
BAR does not change. *)
#define FOO "original definition"
#define BAR FOO
#undef FOO
#define FOO "new definition"
FOO (* expands to "new definition" *)
BAR (* expands to "original definition" *)
(* This test shows that a formal parameter can shadow a previously
defined macro. *)
#define F(FOO) FOO
F(42) (* expands to 42 *)
(* This test shows that two formal parameters can have the same
name. In that case, the second parameter shadows the first one. *)
#define G(X, X) X+X
G(42,23) (* expands to 23+23 *)
(* This test shows that it is OK to pass an empty argument to a macro
that expects one parameter. This is interpreted as passing one
empty argument. *)
#define expect(x) show(x)
expect(42)
expect("23")
expect()

View file

@ -0,0 +1,36 @@
# 1 "lexical.cppo"
(* This test shows that the definition of BAR captures the original
definition of FOO, so even if FOO is redefined, the expansion of
BAR does not change. *)
# 8 "lexical.cppo"
"new definition"
# 8 "lexical.cppo"
(* expands to "new definition" *)
# 9 "lexical.cppo"
"original definition"
# 9 "lexical.cppo"
(* expands to "original definition" *)
(* This test shows that a formal parameter can shadow a previously
defined macro. *)
# 14 "lexical.cppo"
42
# 14 "lexical.cppo"
(* expands to 42 *)
(* This test shows that two formal parameters can have the same
name. In that case, the second parameter shadows the first one. *)
# 19 "lexical.cppo"
23+23
# 19 "lexical.cppo"
(* expands to 23+23 *)
(* This test shows that it is OK to pass an empty argument to a macro
that expects one parameter. This is interpreted as passing one
empty argument. *)
# 25 "lexical.cppo"
show(42)
# 26 "lexical.cppo"
show("23")
# 27 "lexical.cppo"
show()

View file

@ -0,0 +1,8 @@
#define loc __FILE__ __LINE__
loc
X(loc)
X(loc)
X(Y(loc))
#define F(x) loc
F()

View file

@ -0,0 +1,21 @@
# 2 "loc.cppo"
"loc.cppo" 2
# 3 "loc.cppo"
X(
# 3 "loc.cppo"
"loc.cppo" 3
# 3 "loc.cppo"
)
X(
# 4 "loc.cppo"
"loc.cppo" 4
# 4 "loc.cppo"
)
X(Y(
# 5 "loc.cppo"
"loc.cppo" 5
# 5 "loc.cppo"
))
# 8 "loc.cppo"
"loc.cppo" 8

View file

@ -0,0 +1,12 @@
(* A common problem: *)
#def TWICE(e)
e + e
(* missing #enddef here *)
let f x =
TWICE(x)
(* The error is detected by the parser at the end of the file,
but we are able to report the location of the #def as the
source of the problem. *)

View file

@ -0,0 +1,2 @@
Error: File "missing_enddef.cppo", line 3, characters 0-13
Error: This #def is never closed: perhaps #enddef is missing

View file

@ -0,0 +1,14 @@
(* A common problem: *)
#scope
#def TWICE(e)
e + e
#enddef
(* missing #endscope here *)
let f x =
TWICE(x)
(* The error is detected by the parser at the end of the file,
but we are able to report the location of the #scope as the
source of the problem. *)

View file

@ -0,0 +1,2 @@
Error: File "missing_endscope.cppo", line 3, characters 0-6
Error: This #scope is never closed: perhaps #endscope is missing

View file

@ -0,0 +1,3 @@
#define F(x, y) <x> <y>
F((1, (2)), 34)
F((1\,\(2\)), 34)

View file

@ -0,0 +1,4 @@
# 2 "paren_arg.cppo"
<(1, (2))> < 34>
# 3 "paren_arg.cppo"
<(1 , (2 ))> < 34>

View file

@ -0,0 +1,85 @@
(* This example shows that the definition of FOO that is nested inside
the (multi-line) definition of BAR affects only the body of the
definition of BAR. It does not affect the text that follows a call
to BAR. So, a multi-line macro definition acts as a scope delimiter. *)
#def BAR
#define FOO "definition of FOO inside BAR"
FOO (* expands to "definition of FOO inside BAR" *)
#enddef
#define FOO "definition of FOO at the top level"
FOO (* expands to "definition of FOO at the top level" *)
BAR
FOO (* expands to "definition of FOO at the top level" *)
(* If one wishes to delimit a scope, without actually defining a macro,
one can use #scope ... #endscope. *)
#scope
#define HELLO "first definition of HELLO"
HELLO (* expands to "first definition of HELLO" *)
#endscope
#scope
#define HELLO "second definition of HELLO"
HELLO (* expands to "second definition of HELLO" *)
#endscope
HELLO (* this does not expand *)
(* The effect of #scope ... #endscope can be simulated by writing
#def DUMMY ... #enddef DUMMY #undef DUMMY
but this is a bit unnatural. *)
#def DUMMY
#define HELLO "definition of HELLO inside the scope"
HELLO (* expands to "definition of HELLO inside the scope" *)
#enddef
DUMMY
#undef DUMMY
HELLO (* this does not expand *)
(* Another simple example. *)
#scope
#define HI "I am defined"
let x = HI (* expands to "I am defined" *)
#endscope
#define HI 42
let y = HI (* expands to 42 *)
(* Check that the effect of #undef is also local.
This example relies on the above definition of HI. *)
#scope
#undef HI
let qwd = HI (* HI is not recognized as a macro and expands to itself *)
#endscope
let z = HI (* expands to 42 *)
(* Scopes can be nested. *)
#define LEVEL 0
let x = LEVEL (* expands to 0 *)
#scope
#undef LEVEL
#define LEVEL 1
let y = LEVEL (* expands to 1 *)
#scope
#undef LEVEL
#define LEVEL 2
let z = LEVEL (* expands to 2 *)
#endscope
let _ = LEVEL (* expands to 1 *)
#endscope
let _ = LEVEL (* expands to 0 *)
(* Another example of nesting. *)
#scope
#define HELLO "Hello, "
#scope
#define MAN "man"
let message1 = HELLO ^ MAN
#endscope
(* Here, MAN is no longer defined, but HELLO still is. *)
let message2 = HELLO ^ "world"
#endscope

View file

@ -0,0 +1,131 @@
# 1 "scope.cppo"
(* This example shows that the definition of FOO that is nested inside
the (multi-line) definition of BAR affects only the body of the
definition of BAR. It does not affect the text that follows a call
to BAR. So, a multi-line macro definition acts as a scope delimiter. *)
# 11 "scope.cppo"
"definition of FOO at the top level"
# 11 "scope.cppo"
(* expands to "definition of FOO at the top level" *)
# 12 "scope.cppo"
"definition of FOO inside BAR" (* expands to "definition of FOO inside BAR" *)
# 13 "scope.cppo"
"definition of FOO at the top level"
# 13 "scope.cppo"
(* expands to "definition of FOO at the top level" *)
(* If one wishes to delimit a scope, without actually defining a macro,
one can use #scope ... #endscope. *)
# 20 "scope.cppo"
"first definition of HELLO"
# 20 "scope.cppo"
(* expands to "first definition of HELLO" *)
# 24 "scope.cppo"
"second definition of HELLO"
# 24 "scope.cppo"
(* expands to "second definition of HELLO" *)
HELLO (* this does not expand *)
(* The effect of #scope ... #endscope can be simulated by writing
#def DUMMY ... #enddef DUMMY #undef DUMMY
but this is a bit unnatural. *)
# 36 "scope.cppo"
"definition of HELLO inside the scope" (* expands to "definition of HELLO inside the scope" *)
# 38 "scope.cppo"
HELLO (* this does not expand *)
(* Another simple example. *)
# 44 "scope.cppo"
let x =
# 44 "scope.cppo"
"I am defined"
# 44 "scope.cppo"
(* expands to "I am defined" *)
# 47 "scope.cppo"
let y =
# 47 "scope.cppo"
42
# 47 "scope.cppo"
(* expands to 42 *)
(* Check that the effect of #undef is also local.
This example relies on the above definition of HI. *)
# 54 "scope.cppo"
let qwd = HI (* HI is not recognized as a macro and expands to itself *)
let z =
# 56 "scope.cppo"
42
# 56 "scope.cppo"
(* expands to 42 *)
(* Scopes can be nested. *)
# 61 "scope.cppo"
let x =
# 61 "scope.cppo"
0
# 61 "scope.cppo"
(* expands to 0 *)
# 65 "scope.cppo"
let y =
# 65 "scope.cppo"
1
# 65 "scope.cppo"
(* expands to 1 *)
# 69 "scope.cppo"
let z =
# 69 "scope.cppo"
2
# 69 "scope.cppo"
(* expands to 2 *)
let _ =
# 71 "scope.cppo"
1
# 71 "scope.cppo"
(* expands to 1 *)
let _ =
# 73 "scope.cppo"
0
# 73 "scope.cppo"
(* expands to 0 *)
(* Another example of nesting. *)
# 81 "scope.cppo"
let message1 =
# 81 "scope.cppo"
"Hello, "
# 81 "scope.cppo"
^
# 81 "scope.cppo"
"man"
# 83 "scope.cppo"
(* Here, MAN is no longer defined, but HELLO still is. *)
let message2 =
# 84 "scope.cppo"
"Hello, "
# 84 "scope.cppo"
^ "world"

View file

@ -0,0 +1,5 @@
#define FOO 24
#define APPLY(F : [.], X) F(X)
APPLY(FOO, 42)
(* invalid because APPLY expects a macro of type [.]
but FOO has type . *)

View file

@ -0,0 +1,3 @@
Error: File "shape_mismatch.cppo", line 3, characters 6-9
Error: A macro of type [.] was expected, but
a macro of type . was provided

View file

@ -0,0 +1,13 @@
#! /bin/sh -e
echo "# $2"
echo "(*"
cat "$1"
echo "*)"
echo "(*"
echo " Environment variables:"
echo " CPPO_FILE=$CPPO_FILE"
echo " CPPO_FIRST_LINE=$CPPO_FIRST_LINE"
echo " CPPO_LAST_LINE=$CPPO_LAST_LINE"
echo "*)"
echo "# $3"

View file

@ -0,0 +1,146 @@
(* comment *)
#define pi 3.14
f(1)
#define f(x) x+pi
f(2)
#undef pi
f(3)
#ifdef g
"g" is defined
#else
"g" is not defined
#endif
#define a(x) b()
#define b(x) a()
a()
debug("a")
debug("b")
#define z 123
#define y z
#define x y
#if x lsl 1 = 2*123
#if 1 = 2
#error "test"
#endif
success
#else
failure
#endif
#define test_multiline \
"abc\
xyz
def" \
(* 123 \
789
456 *)
test_multiline
#define test_args(x, y) x y
test_args("a","b")
#define test_argc(x) x y
test_argc(aa\,bb)
#define test_esc(x) x
test_esc(\,\)\()
blah #define xyz
#ifdef xyz
#error "xyz should not have been defined"
#endif
#define sticky1(x) _
#define sticky2(x) sticky1()_ (* the 2 underscores should be space-separated *)
sticky2()
#define empty1
#define empty2 +empty1+ (* there should be some space between the pluses *)
empty2
(* (* nested comment with single single quote: ' *) "*)" *)
#define arg
obj
\# define arg
' (* lone single quote *)
#define one 1
one = 1
#undef x
#define x #
x is #
#undef one
#define one 1
#if (one+one = 100 + \
64 lsr 3 / 4 - lnot lnot 100) && \
1 + 3 * 5 = 16 && \
22 mod 7 = 1 && \
lnot 0 = 0xffffffffffffffff && \
-1 asr 100 = -1 && \
-1 land (1 lsl 1 lsr 1) = 1 && \
-1 lor 1 = -1 && \
-2 lxor 1 = -1 && \
lnot -1 = 0 && \
true && not false && defined one && \
(true || true && false)
good maths
#else
#error "math error"
#endif
#undef f
#undef g
#undef x
#undef y
#define trace(f) \
let f x = \
printf "call %s\n%!" STRINGIFY(f); \
let y = f x in \
printf "return %s\n%!" STRINGIFY(f); \
y \
;;
trace(g)
#define field(name,type) \
val mutable name : type option \
method CONCAT(get_, name) = name \
method CONCAT(set_, name) x = name <- Some x
class foo () =
object
field(field_1, int)
field(field_2, string)
end
#define DEBUG(x) \
(if !debug then \
eprintf "[debug] %s %i: " __FILE__ __LINE__; \
eprintf x; \
eprintf "\n")
DEBUG("test1 %i %i" x y)
DEBUG("test2 %i" x)
#include "incl.cppo"
# 123456
#789 "test"
#include "incl.cppo"
#define debug(s) Printf.eprintf "%S %i: %s\n%!" __FILE__ __LINE__ s
end

View file

@ -0,0 +1,142 @@
# 1 "test.cppo"
(* comment *)
# 4 "test.cppo"
f(1)
# 6 "test.cppo"
2+ 3.14
# 8 "test.cppo"
3+ 3.14
# 13 "test.cppo"
"g" is not defined
# 18 "test.cppo"
b()
# 20 "test.cppo"
debug("a")
debug("b")
# 33 "test.cppo"
success
# 45 "test.cppo"
"abc\
xyz
def"
(* 123 \
789
456 *)
# 48 "test.cppo"
"a" "b"
# 51 "test.cppo"
aa ,bb 123
# 54 "test.cppo"
, ) (
# 56 "test.cppo"
blah #define xyz
# 63 "test.cppo"
_ _ (* the 2 underscores should be space-separated *)
# 67 "test.cppo"
+ + (* there should be some space between the pluses *)
# 69 "test.cppo"
(* (* nested comment with single single quote: ' *) "*)" *)
# 72 "test.cppo"
obj
# define
# 73 "test.cppo"
# 75 "test.cppo"
' (* lone single quote *)
# 78 "test.cppo"
1
# 78 "test.cppo"
= 1
# 82 "test.cppo"
#
# 82 "test.cppo"
is #
# 98 "test.cppo"
good maths
# 117 "test.cppo"
let g x =
printf "call %s\n%!" "g";
let y = g x in
printf "return %s\n%!" "g";
y
;;
# 124 "test.cppo"
class foo () =
object
# 126 "test.cppo"
val mutable field_1 : int option
method get_field_1 = field_1
method set_field_1 x = field_1 <- Some x
# 127 "test.cppo"
val mutable field_2 : string option
method get_field_2 = field_2
method set_field_2 x = field_2 <- Some x
# 128 "test.cppo"
end
# 135 "test.cppo"
(if !debug then
eprintf "[debug] %s %i: " "test.cppo" 135 ;
eprintf "test1 %i %i" x y;
eprintf "\n")
# 136 "test.cppo"
(if !debug then
eprintf "[debug] %s %i: " "test.cppo" 136 ;
eprintf "test2 %i" x;
eprintf "\n")
# 1 "incl.cppo"
included
# 1 "incl2.cppo"
ok
# 139 "test.cppo"
# 123456
# 789 "test"
# 1 "incl.cppo"
included
# 1 "incl2.cppo"
ok
# 793 "test"
end

View file

@ -0,0 +1,38 @@
#if (2 + 2, 5) < (4, 5)
mountain
#error ""
#else
pistachios
#endif
#if (3 * 3) = 10 - 1
trees
#else
rocks
#error ""
#endif
#if (1) = (1)
waves
#else
sharks
#error ""
#endif
#define x 11
#if (x, 2) <> (x, 4/2)
honey
#error ""
#else
bees
#endif
#define tuple (0, -5, 3)
#define tuple2 tuple
#if (0, -5, x) > tuple2
steamboat
#else
koalas
#error ""
#endif

View file

@ -0,0 +1,20 @@
# 5 "tuple.cppo"
pistachios
# 9 "tuple.cppo"
trees
# 16 "tuple.cppo"
waves
# 28 "tuple.cppo"
bees
# 34 "tuple.cppo"
steamboat

View file

@ -0,0 +1,4 @@
#define APPLY(F : [.], X) F(X)
APPLY(FOO, 42)
(* invalid because APPLY expects a macro as an argument:
but FOO is not defined. *)

View file

@ -0,0 +1,2 @@
Error: File "undefined.cppo", line 2, characters 6-9
Error: The macro 'FOO' is not defined

View file

@ -0,0 +1,14 @@
#ifdef whatever
(
#else
let a = 1 in
let b = 2 in
(a ||
#endif
b)
#define F(x, y) (x + y)
F(1,(2+3))
)
(

View file

@ -0,0 +1,15 @@
# 4 "unmatched.cppo"
let a = 1 in
let b = 2 in
(a ||
# 9 "unmatched.cppo"
b)
# 12 "unmatched.cppo"
(1 + (2+3))
# 13 "unmatched.cppo"
)
(

View file

@ -0,0 +1,34 @@
#if X_VERSION < (123, 0, 0)
alligators
#error ""
#else
Cape buffalos
#endif
#define v X_VERSION
#if v = (X_MAJOR, X_MINOR, X_PATCH)
onion rings
#else
gazpacho
#error ""
#endif
major: X_MAJOR
minor: X_MINOR
patch: X_PATCH
#ifdef X_PRERELEASE
prerelease: X_PRERELEASE
#else
#error ""
#endif
#ifdef X_BUILD
build: X_BUILD
#else
#error ""
#endif
Coq: COQ_VERSION
OCaml pre-release: OCAML_PRERELEASE

View file

@ -0,0 +1,42 @@
# 5 "version.cppo"
Cape buffalos
# 10 "version.cppo"
onion rings
# 16 "version.cppo"
major:
# 16 "version.cppo"
123
# 17 "version.cppo"
minor:
# 17 "version.cppo"
05
# 18 "version.cppo"
patch:
# 18 "version.cppo"
2
# 21 "version.cppo"
prerelease:
# 21 "version.cppo"
alpha.1
# 27 "version.cppo"
build:
# 27 "version.cppo"
foo-2.1
# 32 "version.cppo"
Coq:
# 32 "version.cppo"
(8, 13, 0)
# 34 "version.cppo"
OCaml pre-release:
# 34 "version.cppo"
alpha1