|
| 1 | +-- | Implement HOA controller in C |
| 2 | +module TSL.HOA.C |
| 3 | + ( implement, |
| 4 | + ) |
| 5 | +where |
| 6 | + |
| 7 | +import Data.List (intercalate) |
| 8 | +import qualified Data.Set as Set |
| 9 | +import qualified Hanoi as H |
| 10 | +import TSL.HOA.Codegen (codegen, splitInputsCellsOutputs) |
| 11 | +import TSL.HOA.Imp |
| 12 | + ( ImpConfig (..), |
| 13 | + cellOutputNextPrefix, |
| 14 | + withConfig', |
| 15 | + ) |
| 16 | + |
| 17 | +implement :: Bool -> H.HOA -> String |
| 18 | +implement isCounterStrat hoa = |
| 19 | + let prog = codegen hoa |
| 20 | + controller = withConfig' config isCounterStrat prog |
| 21 | + (is', cs', os') = splitInputsCellsOutputs prog |
| 22 | + is = Set.toList is' |
| 23 | + cs = Set.toList cs' |
| 24 | + os = Set.toList os' |
| 25 | + allCellsOutputs = cs ++ os |
| 26 | + allVars = is ++ allCellsOutputs |
| 27 | + in -- includes |
| 28 | + "#include <stdbool.h>\n\n" |
| 29 | + -- global variable declarations |
| 30 | + ++ concatMap (\v -> "int " ++ v ++ ";\n") allVars |
| 31 | + ++ "\n" |
| 32 | + -- read_inputs stub (game harness provides the real one) |
| 33 | + ++ "void read_inputs(void) { }\n\n" |
| 34 | + -- main function |
| 35 | + ++ "void main() {\n" |
| 36 | + ++ " int currentState = 0;\n" |
| 37 | + -- _next_ variable declarations for cells and outputs |
| 38 | + ++ concatMap (\v -> " int " ++ cellOutputNextPrefix ++ v ++ ";\n") allCellsOutputs |
| 39 | + ++ "\n" |
| 40 | + ++ " while (1) {\n" |
| 41 | + ++ " read_inputs();\n\n" |
| 42 | + -- default identity: _next_var = var for each cell |
| 43 | + ++ concatMap (\v -> " " ++ cellOutputNextPrefix ++ v ++ " = " ++ v ++ ";\n") allCellsOutputs |
| 44 | + ++ "\n" |
| 45 | + -- controller state machine logic |
| 46 | + ++ controller |
| 47 | + ++ "\n\n" |
| 48 | + -- copy _next_ values back to real variables |
| 49 | + ++ concatMap (\v -> " " ++ v ++ " = " ++ cellOutputNextPrefix ++ v ++ ";\n") allCellsOutputs |
| 50 | + ++ " }\n" |
| 51 | + ++ "}\n" |
| 52 | + |
| 53 | +config :: ImpConfig |
| 54 | +config = |
| 55 | + ImpConfig |
| 56 | + { -- binary functions |
| 57 | + impAdd = "+", |
| 58 | + impSub = "-", |
| 59 | + impMult = "*", |
| 60 | + impDiv = "/", |
| 61 | + -- binary comparators |
| 62 | + impEq = "==", |
| 63 | + impNeq = "!=", |
| 64 | + impLt = "<", |
| 65 | + impGt = ">", |
| 66 | + impLte = "<=", |
| 67 | + impGte = ">=", |
| 68 | + -- logic |
| 69 | + impAnd = "&&", |
| 70 | + impTrue = "true", |
| 71 | + impFalse = "false", |
| 72 | + impNot = "!", |
| 73 | + -- language constructs |
| 74 | + impIf = "if", |
| 75 | + impElif = "else if", |
| 76 | + impCondition = \c -> "(" ++ c ++ ")", |
| 77 | + impFuncApp = \f args -> f ++ "(" ++ intercalate ", " args ++ ")", |
| 78 | + impAssign = \x y -> x ++ " = " ++ y ++ ";", |
| 79 | + impIndent = \n -> replicate (2 * n) ' ', |
| 80 | + impBlockStart = " {", |
| 81 | + impBlockEnd = "}", |
| 82 | + -- indent level 2 = 4 spaces, matching nesting inside main() { while(1) { ... } } |
| 83 | + impInitialIndent = 2 |
| 84 | + } |
0 commit comments