@@ -20,7 +20,7 @@ import Data.Map.Strict (Map)
2020import System.FilePath ((</>) )
2121
2222--------------------------------------------------------------------------------
23- -- Core generators
23+ -- Core (stateless) generators
2424--------------------------------------------------------------------------------
2525
2626instance Arbitrary a => Arbitrary (Value a ) where
@@ -68,7 +68,6 @@ instance Arbitrary a => Arbitrary (TypeSpec a) where
6868maybeWrapper :: Gen a -> Gen (Maybe a )
6969maybeWrapper gen = oneof [pure Nothing , Just <$> gen]
7070
71-
7271nullSpan :: SrcSpan
7372nullSpan = SrcSpan initPosition initPosition
7473
@@ -133,10 +132,10 @@ genDecl = do
133132genDecls :: Int -> GenM [Statement A0 ]
134133genDecls n = replicateM n genDecl
135134
136- -- | Top-level runner: generate a subroutine with a growing set of declarations.
137- -- Uses QuickCheck's 'sized' so the number of declarations scales with test size.
135+ -- | Generate a program unit with a growing set of declarations.
138136instance Arbitrary (ProgramUnit A0 ) where
139137 arbitrary = sized $ \ sz -> do
138+ -- Uses QuickCheck's 'sized' so the number of declarations scales with test size.
140139 let numDecls = max 1 (sz `div` 5 )
141140 (decls, env) <- runStateT (genDecls numDecls) Map. empty
142141 -- env is now available for generating expressions / further statements
@@ -151,20 +150,23 @@ instance Arbitrary (ProgramUnit A0) where
151150 printAllEnd env =
152151 [ BlStatement () nullSpan Nothing (StPrint () nullSpan (ExpValue () nullSpan ValStar ) (fromList' () (map (\ n -> ExpValue () nullSpan (ValVariable n)) (Map. keys env)))) ]
153152
154-
155153instance ArbitraryCtxt (Statement A0 ) where
154+ -- Bias assignments over print statements
156155 arbitraryCtxt = oneofCtxt (printer : replicate 3 assignment)
157156 where
158157 assignment :: GenM (Statement A0 )
159158 assignment = do
160159 (lvar, typ) <- pickVar
161160 expr <- genTypedExpression typ
162161 pure $ StExpressionAssign () nullSpan (ExpValue () nullSpan (ValVariable lvar)) expr
162+
163163 printer :: GenM (Statement A0 )
164164 printer = do
165- expr <- genVarRef
165+ (name, _) <- pickVar
166+ let expr = ExpValue () nullSpan (ValVariable name)
166167 pure $ StPrint () nullSpan (ExpValue () nullSpan ValStar ) (fromList' () [expr])
167168
169+ -- Synthesise an expression of the given type
168170genTypedExpression :: TypeSpec A0 -> GenM (Expression A0 )
169171genTypedExpression typeSpec = do
170172 -- For simplicity, we just generate a variable reference of the correct type.
@@ -180,6 +182,7 @@ genTypedExpression typeSpec = do
180182 , genTypedValue typeSpec ] -- In a full implementation, we would generate more complex expressions
181183 pure value
182184
185+ -- Synthesise a value of the given type
183186genTypedValue :: TypeSpec A0 -> GenM (Expression A0 )
184187genTypedValue (TypeSpec _ _ baseType _) = case baseType of
185188 TypeInteger -> do
@@ -192,7 +195,9 @@ genTypedValue (TypeSpec _ _ baseType _) = case baseType of
192195 b <- liftGen (arbitrary :: Gen Bool )
193196 pure $ ExpValue () nullSpan (ValLogical b Nothing )
194197 TypeCharacter -> do
195- s <- liftGen (arbitrary :: Gen String )
198+ n <- liftGen $ choose (0 , 20 )
199+ -- TODO: consider utf-8 because maybe this is somewhere things break in compilers
200+ s <- liftGen $ vectorOf n (choose (' ' , ' ~' ))
196201 pure $ ExpValue () nullSpan (ValString s)
197202
198203instance ArbitraryCtxt a => ArbitraryCtxt [a ] where
@@ -210,11 +215,6 @@ pickVar = do
210215 env <- get
211216 liftGen $ elements (Map. toList env)
212217
213- genVarRef :: GenM (Expression A0 )
214- genVarRef = do
215- (name, _) <- pickVar
216- pure $ ExpValue () nullSpan (ValVariable name)
217-
218218--------------------------------------------------------------------------------
219219-- Demonstration / experimentation
220220--------------------------------------------------------------------------------
0 commit comments