1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
(* Copyright 2012 Ian Hinder
This file is part of Kranc.
Kranc is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Kranc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Kranc; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)
BeginPackage["ParamCheck`", {"Errors`", "Helpers`", "Kranc`", "CodeGenCactus`",
"CodeGenC`", "CodeGen`", "CodeGenKranc`", "Code`", "Object`"}];
ParameterCheckSource;
ParameterCheckSchedule;
ParamCheckProcessCode;
Begin["`Private`"];
DefFn[
ParameterCheckSource[thornName_String, conditions_List] :=
{Map[IncludeFile,
{"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h"}],
DefineCCTKFunction[
thornName<>"_ParamCheck", "void",
ConditionalOnParameterTextual[
"CCTK_MyProc(cctkGH) == 0",
Map[checkCondition, conditions]]]}];
DefFn[
ParameterCheckSchedule[thornName_String] :=
{Name -> thornName<>"_ParamCheck",
SchedulePoint -> "at PARAMCHECK",
Options -> "global",
Language -> "C",
Comment -> "Check parameter consistency"}];
DefFn[checkCondition[{cond_, error_String}] :=
Module[
{paramPattern, paren, renderbool, rendervalue},
paramPattern = Except[True | False, _Symbol | _Parameter];
paren[x_] := {"(", x, ")"};
renderbool[Equal[a:paramPattern,b_String]] :=
{"CCTK_EQUALS(", rendervalue[a], ",\"", b, "\")"};
(* Note: We don't have postfix operators, so we don't need
parentheses for prefix operators *)
renderbool[Unequal[a:paramPattern,b_String]] := {"!", renderbool[a==b]};
(* Note: == and != don't nest, so we don't need parentheses here *)
renderbool[Equal[a:paramPattern,b_?NumberQ]] := {rendervalue[a], " == ", rendervalue[b]};
renderbool[Unequal[a:paramPattern,b_?NumberQ]] := {rendervalue[a], " != ", rendervalue[b]};
(* Note: if == or != are inside && or ||, we could omit the parentheses *)
renderbool[HoldPattern[And[as__]]] :=
Riffle[Map[paren[renderbool[#]]&, List[as]], " && "];
renderbool[HoldPattern[Or[as__]]] :=
Riffle[Map[paren[renderbool[#]]&, List[as]], " || "];
renderbool[Not[a_]] := {"!", paren[renderbool[a]]};
renderbool[a:paramPattern] := ToString[a/.(Parameter[x_]->x)]; (* Boolean parameter *)
renderbool[x_] := ThrowError["Unexpected value in run-time conditional expression (boolean):", x, "in", cond];
(* rendervalue[a_String] := a; -- Allow literal pass-through *)
rendervalue[a_?NumberQ] := ToString[a];
rendervalue[Parameter[a_String]] := a;
(* TODO: pass in valid parameters *)
rendervalue[a_ (*/; MemberQ[params,a] *) ] := ToString[a];
(* rendervalue[x_] := ThrowError["Unexpected value in run-time conditional expression (value):", x, "in", cond]; *)
ConditionalOnParameterTextual[
renderbool[cond],
{"CCTK_WARN(CCTK_WARN_ABORT, ", StringDrop[Stringify[error],-1], ");\n"}]]];
Options[ParamCheckProcessCode] = ThornOptions;
DefFn[
ParamCheckProcessCode[cIn_Code, opts:OptionsPattern[]] :=
Module[
{c = cIn},
If[Length[OptionValue[ParameterConditions]] > 0,
c = AppendObjectField[
c, "Sources",
{Filename -> "ParamCheck.cc",
Contents -> ParameterCheckSource[GetObjectField[c, "Name"],
OptionValue[ParameterConditions]]}]];
c]];
End[];
EndPackage[];
|