Changeset 7190
- Timestamp:
- 09/28/05 23:08:26 (3 years ago)
- Files:
-
- 1 added
- 3 removed
- 17 modified
-
Pugs.cabal (added)
-
pil.cabal (deleted)
-
src/Pugs/AST/Internals.hs (modified) (1 diff)
-
src/Pugs/AST/Types.hs (deleted)
-
src/Pugs/Context.hs (deleted)
-
src/Pugs/Eval.hs (modified) (1 diff)
-
src/Pugs/Eval/Var.hs (modified) (1 diff)
-
src/Pugs/Monads.hs (modified) (1 diff)
-
src/Pugs/Parser.hs (modified) (1 diff)
-
src/Pugs/Run.hs (modified) (1 diff)
-
src/Pugs/Types.hs (modified) (2 diffs)
-
src/Pugs/Version.hs (modified) (1 diff)
-
t/subroutines/signature_matching.t (modified) (2 diffs)
-
t/var/assigning_refs.t (modified) (5 diffs)
-
t/var/codevars_should_not_autovivify.t (modified) (1 diff)
-
t/var/constant.t (modified) (12 diffs)
-
t/var/is_readonly.t (modified) (3 diffs)
-
t/var/lazy.t (modified) (1 diff)
-
t/var/let.t (modified) (2 diffs)
-
t/var/my.t (modified) (1 diff)
-
t/var/refs_point_to_containers.t (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Pugs/AST/Internals.hs
r7076 r7190 72 72 ) where 73 73 import Pugs.Internals 74 import Pugs.Context75 74 import Pugs.Types 76 75 import Pugs.Cont hiding (shiftT, resetT) -
src/Pugs/Eval.hs
r7135 r7190 35 35 import Pugs.Prim 36 36 import Pugs.Prim.List (op0Zip) 37 import Pugs.Context38 37 import Pugs.Monads 39 38 import Pugs.Pretty -
src/Pugs/Eval/Var.hs
r6672 r7190 16 16 import Pugs.Prim.List (op2Fold, op1HyperPrefix, op1HyperPostfix, op2Hyper) 17 17 import Pugs.Prim.Param (foldParam) 18 import Pugs.Context19 18 import Pugs.Pretty 20 19 import Pugs.Config -
src/Pugs/Monads.hs
r7035 r7190 25 25 import Pugs.Internals 26 26 import Pugs.AST 27 import Pugs.Context28 27 import Pugs.Types 29 28 import Control.Monad.RWS -
src/Pugs/Parser.hs
r7142 r7190 23 23 import Pugs.AST 24 24 import Pugs.Types 25 import Pugs.Context26 25 import Pugs.Version (versnum) 27 26 import Pugs.Lexer -
src/Pugs/Run.hs
r6552 r7190 22 22 import Pugs.Internals 23 23 import Pugs.Config 24 import Pugs.Context25 24 import Pugs.AST 26 25 import Pugs.Types -
src/Pugs/Types.hs
r6826 r7190 12 12 13 13 module Pugs.Types ( 14 Type(..), mkType, anyType, showType, 15 ClassTree, 14 Type(..), mkType, anyType, showType, isaType, isaType', deltaType, 15 ClassTree, initTree, addNode, 16 16 17 17 Cxt(..), … … 169 169 show _ = "<tmvar>" 170 170 171 {-| 172 Count the total number of types in a class tree, including both internal and 173 leaf nodes. 174 175 This is used by 'deltaType' to ensure that incompatible types are always 176 further apart than compatible types. 177 -} 178 countTree :: ClassTree -> Int 179 countTree (Node _ []) = 1 180 countTree (Node _ cs) = 1 + sum (map countTree cs) 181 182 {-| 183 Find the \'difference\' between two types in the given class tree (for MMD 184 purposes and such). 185 186 Identical types (that exist in the class tree) produce 0. Compatible types 187 will produce a small positive number representing their distance. 188 Incompatible will produce a distance larger 189 than any two compatible types. If one (or both) of the types doesn't exist in 190 the tree, the result is a very large number. 191 192 > <scook0> is deltaType supposed to be returning large positive numbers for 193 > types that are actually incompatible? 194 > <autrijus> that is a open design question. 195 > <autrijus> it is that way because we want 196 > <autrijus> '1'+'2' 197 > <autrijus> to work 198 > <scook0> I see 199 > <autrijus> without having to define <+> as Scalar Scalar 200 > <autrijus> I think I did think of leaving a compatibleTypes as remedy 201 > <autrijus> to specify things that are fundamentally uncastable 202 > <scook0> I think I'll just document the current behaviour for now 203 > <autrijus> nod. it is a mess. it really wants a rewrite. 204 -} 205 deltaType :: ClassTree -- ^ Class tree to use for the comparison 206 -> Type -- ^ Base type 207 -> Type -- ^ Possibly-derived type 208 -> Int 209 deltaType = junctivate min max $ \tree base target -> 210 let distance = distanceType tree base target in 211 if distance < 0 212 then countTree tree - distance 213 else distance 214 215 {-| 216 Autothreading of comparisons between junctive types. 217 218 Just as autothreading over value junctions will perform an operation on all 219 junction elements and combine the results back into a junction, this function 220 autothreads some type comparison over all the possible type permutations, 221 then combines the results using two user-specified /functions/. 222 223 E.g. if we want to check whether the type @(Int|Str)@ is a @Num@, we first 224 check whether @Int@ is a @Num@ (@True@), then check whether @Str@ is a num 225 (@False@), then combine the results using the specified disjunctive combiner 226 (in this case Haskell's @(||)@). The result is thus @True@. 227 -} 228 junctivate :: (t -> t -> t) -- ^ Function to combine results over disjunctive 229 -- (@|@) types 230 -> (t -> t -> t) -- ^ Function to combine results over conjunctive 231 -- (@\&@) types 232 -> (ClassTree -> Type -> Type -> t) 233 -- ^ Function that will actually perform the 234 -- comparison (on non-junctive types) 235 -> ClassTree -- ^ Class tree to pass to the comparison function 236 -> Type -- ^ First type to compare 237 -> Type -- ^ Second type to compare 238 -> t 239 junctivate or and f tree base target 240 | TypeOr t1 t2 <- target 241 = redo base t1 `or` redo base t2 242 | TypeOr b1 b2 <- base 243 = redo b1 target `or` redo b2 target 244 | TypeAnd t1 t2 <- target 245 = redo base t1 `and` redo base t2 246 | TypeAnd b1 b2 <- base 247 = redo b1 target `and` redo b2 target 248 | otherwise 249 = f tree base target 250 where 251 redo = junctivate or and f tree 252 253 -- When saying Int.isa(Scalar), Scalar is the base, Int is the target 254 {-| 255 A more convenient version of 'isaType\'' that automatically converts the base 256 type string into an actual 'Type' value. 257 -} 258 isaType :: ClassTree -- ^ Class tree to use for the comparison 259 -> String -- ^ Base type 260 -> Type -- ^ Possibly-derived type 261 -> Bool 262 isaType tree base target = isaType' tree (mkType base) target 263 264 {-| 265 Return true if the second type (the \'target\') is derived-from or equal-to the 266 first type (the \'base\'), in the context of the given class tree. 267 268 This function will autothread over junctive types. 269 -} 270 isaType' :: ClassTree -- ^ Class tree to use for the comparison 271 -> Type -- ^ Base type 272 -> Type -- ^ Possibly-derived type 273 -> Bool 274 isaType' = junctivate (||) (&&) $ \tree base target -> 275 distanceType tree base target >= 0 276 277 {-| 278 Compute the \'distance\' between two types by applying 'findList' to each of 279 them, and passing the resulting type chains to 'compareList'. 280 281 See 'compareList' for further details. 282 -} 283 distanceType :: ClassTree -> Type -> Type -> Int 284 distanceType tree base target = compareList l1 l2 285 -- | not (castOk base target) = 0 286 -- | otherwise = compareList l1 l2 287 where 288 l1 = findList base tree 289 l2 = findList target tree 290 291 {- 292 -- | (This is currently unused...) 293 castOk :: a -> b -> Bool 294 castOk _ _ = True 295 -} 296 297 {-| 298 Take two inheritance chains produced by 'findList', and determine how 299 \'compatible\' the first one is with the second. 300 301 Compatible types will produce a number indicating how distant they are. 302 Incompatible types produce a negative number indicating how much the base type 303 would need to be relaxed. If one (or both) types doesn't exist in the tree, a 304 large negative number is produced 305 306 E.g.: 307 308 * comparing @Int@ and @Int@ will produce 0 309 310 * comparing @Scalar@ and @String@ will produce 1 311 312 * comparing @Num@ and @Scalar@ will produce -2 313 314 * comparing @Blorple@ and @Method@ will produce -999 (or similar) 315 -} 316 compareList :: [Type] -- ^ Base type's chain 317 -> [Type] -- ^ Possibly-derived type's chain 318 -> Int 319 compareList [] _ = -999 -- XXX hack (nonexistent base type?) 320 compareList _ [] = -999 -- XXX hack (incompatible types) 321 compareList l1 l2 322 | last l1 `elem` l2 = length(l2 \\ l1) -- compatible types 323 | last l2 `elem` l1 = - length(l1 \\ l2) -- anti-compatible types 324 | otherwise = compareList l1 (init l2) 325 326 {-| 327 Produce the type \'inheritance\' chain leading from the base type (@Any@) to 328 the given type. 329 330 e.g. 331 332 @ 333 'findList' ('MkType' \"Num\") 'initTree' 334 @ 335 336 will produce the list of types 337 338 @ 339 Any, Void, Object, Scalar, Complex, Num 340 @ 341 342 This function does /not/ expect to be given junctive types. 343 -} 344 findList :: Type -- ^ 'Type' to find the inheritance chain of 345 -> ClassTree -- ^ Class tree to look in 346 -> [Type] 347 findList base (Node l cs) 348 | base == l = [l] 349 | Just ls <- find (not . null) found = l:ls 350 | otherwise = [] 351 where 352 found :: [[Type]] 353 found = map (findList base) cs 354 355 {- 356 {-| 357 Pretty-print the initial class tree, using @Tree@'s @drawTree@. 358 359 (This seems to be a debugging aid, since it's not actually used anywhere.) 360 -} 361 prettyTypes :: String 362 prettyTypes = drawTree $ fmap show initTree 363 -} 364 365 {-| 366 Add a new \'top-level\' type to the class tree, under @Object@. 367 -} 368 addNode :: ClassTree -> Type -> ClassTree 369 addNode (Node obj [Node any (Node item ns:rest), junc]) typ = 370 Node obj [Node any (Node item ((Node typ []):ns):rest), junc] 371 addNode _ _ = error "malformed tree" 372 373 {-| 374 Default class tree, containing all built-in types. 375 -} 376 initTree :: ClassTree 377 initTree = fmap MkType $ Node "Object" 378 [ Node "Any" 379 [ Node "Item" 380 [ Node "List" 381 [ Node "Lazy" 382 [ Node "Array" 383 [ Node "Array::Const" [] 384 , Node "Array::Slice" [] 385 ] 386 , Node "Hash" 387 [ Node "Hash::Const" [] 388 , Node "Hash::Env" [] 389 ] 390 ] 391 , Node "Eager" [] 392 ] 393 , Node "Scalar" 394 [ Node "Complex" 395 [ Node "Num" 396 [ Node "Rat" 397 [ Node "Int" 398 [ Node "Bit" [] ] ] ] ] 399 , Node "Bool" [] 400 , Node "Str" [] 401 , Node "Ref" [] 402 , Node "IO" 403 [ Node "IO::Dir" [] 404 ] 405 , Node "Socket" [] 406 , Node "Thread" [] 407 , Node "Code" 408 [ Node "Routine" 409 [ Node "Sub" 410 [ Node "Method" [] 411 , Node "Submethod" [] -- why isn't this a node off Method? - mugwump 412 ] 413 , Node "Macro" [] ] 414 , Node "Block" [] 415 ] 416 , Node "Rul" [] 417 , Node "Pugs::Internals::VRule" [] 418 , Node "Match" [] 419 , Node "Scalar::Const" [] 420 , Node "Scalar::Proxy" [] 421 , Node "Scalar::Lazy" [] 422 , Node "Scalar::Perl5" [] 423 , Node "Proxy" [] 424 , Node "Control::Caller" [] 425 , Node "Time::Local" [] 426 , Node "Type" 427 [ Node "Package" 428 [ Node "Module" 429 [ Node "Class" 430 [ Node "Role" [] 431 , Node "Grammar" [] 432 ] ] ] ] 433 ] 434 ] 435 , Node "Pair" [] 436 ] 437 , Node "Junction" [] ] 438 -
src/Pugs/Version.hs
r6793 r7190 3 3 {-| 4 4 Version information. 5 6 > Tree and flower and leaf and grass, 7 > Let them pass! Let them pass! 8 > Hill and water under sky, 9 > Pass them by! Pass them by! 10 5 11 -} 6 12 -
t/subroutines/signature_matching.t
r5495 r7190 8 8 # check the subroutine with the closest matching signature is called 9 9 10 subearth (+$me) {"me $me"};11 subearth (+$him) {"him $him"};12 subearth (+$me, +$him) {"me $me him $him"};13 subearth (+$me, +$him, +$her) {"me $me him $him her $her"};14 subearth ($me) {"pos $me"};15 subearth ($me, +$you) {"pos $me you $you"};16 subearth ($me, +$her) {"pos $me her $her"};17 subearth ($me, $you) {"pos $me pos $you"};18 subearth ($me, $you, +$her) {"pos $me pos $you her $her"};10 multi earth (+$me) {"me $me"}; 11 multi earth (+$him) {"him $him"}; 12 multi earth (+$me, +$him) {"me $me him $him"}; 13 multi earth (+$me, +$him, +$her) {"me $me him $him her $her"}; 14 multi earth ($me) {"pos $me"}; 15 multi earth ($me, +$you) {"pos $me you $you"}; 16 multi earth ($me, +$her) {"pos $me her $her"}; 17 multi earth ($me, $you) {"pos $me pos $you"}; 18 multi earth ($me, $you, +$her) {"pos $me pos $you her $her"}; 19 19 20 20 is( earth(me => 1), 'me 1', 'named me', :todo<feature>); … … 38 38 # 39 39 40 subwind ($me, $you, +$her) {"pos $me pos $you her $her"};41 subwind ($me, $you) {"pos $me pos $you"};42 subwind ($me, +$her) {"pos $me her $her"};43 subwind ($me, +$you) {"pos $me you $you"};44 subwind ($me) {"pos $me"};45 subwind (+$me, +$him, +$her) {"me $me him $him her $her"};46 subwind (+$me, +$him) {"me $me him $him"};47 subwind (+$him) {"him $him"};48 subwind (+$me) {"me $me"};40 multi wind ($me, $you, +$her) {"pos $me pos $you her $her"}; 41 multi wind ($me, $you) {"pos $me pos $you"}; 42 multi wind ($me, +$her) {"pos $me her $her"}; 43 multi wind ($me, +$you) {"pos $me you $you"}; 44 multi wind ($me) {"pos $me"}; 45 multi wind (+$me, +$him, +$her) {"me $me him $him her $her"}; 46 multi wind (+$me, +$him) {"me $me him $him"}; 47 multi wind (+$him) {"him $him"}; 48 multi wind (+$me) {"me $me"}; 49 49 50 50 is( wind(me => 1), 'me 1', 'named me', :todo<feature>); -
t/var/assigning_refs.t
r6659 r7190 21 21 my @array = ($arrayref); 22 22 23 is +@array, 1, '@array = ($arrayref) does not flatten the arrayref' ;23 is +@array, 1, '@array = ($arrayref) does not flatten the arrayref', :todo<bug>; 24 24 } 25 25 … … 28 28 my @array = $arrayref; 29 29 30 is +@array, 1, '@array = $arrayref does not flatten the arrayref' ;30 is +@array, 1, '@array = $arrayref does not flatten the arrayref', :todo<bug>; 31 31 } 32 32 … … 37 37 my %hash = ($hashref,); 38 38 39 is +%hash, 1, '%hash = ($hashref,) does not flatten the hashref' ;39 is +%hash, 1, '%hash = ($hashref,) does not flatten the hashref', :todo<bug>; 40 40 } 41 41 … … 44 44 my %hash = ($hashref); 45 45 46 is +%hash, 1, '%hash = ($hashref) does not flatten the hashref' ;46 is +%hash, 1, '%hash = ($hashref) does not flatten the hashref', :todo<bug>; 47 47 } 48 48 … … 51 51 my %hash = $hashref; 52 52 53 is +%hash, 1, '%hash = $hashref does not flatten the hashref' ;53 is +%hash, 1, '%hash = $hashref does not flatten the hashref', :todo<bug>; 54 54 } 55 55 -
t/var/codevars_should_not_autovivify.t
r6596 r7190 13 13 dies_ok { 14 14 &New::Package::foo(); 15 }, "...but invoking it should die" ;15 }, "...but invoking it should die", :todo<bug>; -
t/var/constant.t
r6801 r7190 15 15 '; 16 16 17 ok $ok, "declaring a sigilless constant using 'constant' works" ;17 ok $ok, "declaring a sigilless constant using 'constant' works", :todo<feature>; 18 18 } 19 19 … … 26 26 '; 27 27 28 ok $ok, "declaring a constant with a sigil using 'constant' works" ;28 ok $ok, "declaring a constant with a sigil using 'constant' works", :todo<feature>; 29 29 } 30 30 … … 37 37 '; 38 38 39 ok $ok, "declaring a sigilless constant with a type specification using 'constant' works" ;39 ok $ok, "declaring a sigilless constant with a type specification using 'constant' works", :todo<feature>; 40 40 } 41 41 … … 48 48 '; 49 49 50 ok $ok, "declaring an Unicode constant using 'constant' works" ;50 ok $ok, "declaring an Unicode constant using 'constant' works", :todo<feature>; 51 51 } 52 52 … … 64 64 '; 65 65 66 is $ok, 3, "a constant declared using 'constant' is actually constant (1)" ;66 is $ok, 3, "a constant declared using 'constant' is actually constant (1)", :todo<feature>; 67 67 } 68 68 … … 79 79 '; 80 80 81 is $ok, 3, "a constant declared using 'constant' is actually constant (2)" ;81 is $ok, 3, "a constant declared using 'constant' is actually constant (2)", :todo<feature>; 82 82 } 83 83 … … 94 94 '; 95 95 96 is $ok, 3, "a constant declared using 'constant' is actually constant (3)" ;96 is $ok, 3, "a constant declared using 'constant' is actually constant (3)", :todo<feature>; 97 97 } 98 98 … … 109 109 '; 110 110 111 is $ok, 3, "a constant declared using 'constant' is actually constant (4)" ;111 is $ok, 3, "a constant declared using 'constant' is actually constant (4)", :todo<feature>; 112 112 } 113 113 … … 129 129 '; 130 130 131 is $ok, 2, "declaring constants using 'my constant' works" ;131 is $ok, 2, "declaring constants using 'my constant' works", :todo<feature>; 132 132 } 133 133 … … 147 147 '; 148 148 149 is $ok, 3, "constants declared by 'my constant' shadow correctly" ;149 is $ok, 3, "constants declared by 'my constant' shadow correctly", :todo<feature>; 150 150 } 151 151 … … 162 162 '; 163 163 164 is $ok, 2, "declaring constants using 'our constant' works" ;164 is $ok, 2, "declaring constants using 'our constant' works", :todo<feature>; 165 165 } 166 166 … … 177 177 '; 178 178 179 is $ok, 2, "declaring constants using 'constant' creates package-scoped vars" ;179 is $ok, 2, "declaring constants using 'constant' creates package-scoped vars", :todo<feature>; 180 180 } -
t/var/is_readonly.t
r6755 r7190 20 20 is $a, 42, "binding the variable now works"; 21 21 22 dies_ok { $a := 17 }, "but binding it again does not work" ;22 dies_ok { $a := 17 }, "but binding it again does not work", :todo<feature>; 23 23 } 24 24 … … 28 28 29 29 $a := 42; 30 ok (try{ exists $a }), "exists() returns true now" ;30 ok (try{ exists $a }), "exists() returns true now", :todo<feature>; 31 31 } 32 32 … … 34 34 my $a = 3; 35 35 36 ok (try{ exists $a }), "exists() on a plain normal initialized variable returns true" ;36 ok (try{ exists $a }), "exists() on a plain normal initialized variable returns true", :todo<feature>; 37 37 } -
t/var/lazy.t
r6925 r7190 34 34 35 35 is $var, 42, 'our lazy var still has the correct value'; 36 is $was_in_lazy, 1, 'our lazy block was not executed again' ;36 is $was_in_lazy, 1, 'our lazy block was not executed again', :todo<bug>; 37 37 } 38 38 -
t/var/let.t
r6603 r7190 17 17 1; 18 18 } 19 is $a, 23, "let() should not restore the variable, as our block exited succesfully (1)" ;19 is $a, 23, "let() should not restore the variable, as our block exited succesfully (1)", :todo<feature>; 20 20 } 21 21 … … 40 40 let $a = 23; 41 41 is $a, 23, "let() changed the variable (2-1)"; 42 is $get_a(), 23, "let() changed the variable (2-2)" ;42 is $get_a(), 23, "let() changed the variable (2-2)", :todo<feature>; 43 43 1; 44 44 } 45 is $a, 23, "let() should not restore the variable, as our block exited succesfully (2)" ;45 is $a, 23, "let() should not restore the variable, as our block exited succesfully (2)", :todo<feature>; 46 46 } 47 47 -
t/var/my.t
r6938 r7190 11 11 12 12 { 13 dies_ok { my $x; my $x }, "test declare my() variable twice in same scope";13 is(eval('my $x; my $x; 1'), undef, "test declare my() variable twice in same scope"); 14 14 } 15 15 -
t/var/refs_point_to_containers.t
r6573 r7190 14 14 15 15 $num = 4; 16 is $$ref, 4, "refs to scalars point to containers, not cells or even values (1)" ;16 is $$ref, 4, "refs to scalars point to containers, not cells or even values (1)", :todo<bug>; 17 17 18 18 $num := 5; 19 is $$ref, 5, "refs to scalars point to containers, not cells or even values (2)" ;19 is $$ref, 5, "refs to scalars point to containers, not cells or even values (2)", :todo<bug>; 20 20 } 21 21 … … 26 26 27 27 @array[1] = 3; 28 is $$ref, 3, "refs to arrays point to containers, not cells or even values (1)" ;28 is $$ref, 3, "refs to arrays point to containers, not cells or even values (1)", :todo<bug>; 29 29 30 30 try { @array[1] := 4 }; 31 is $$ref, 4, "refs to arrays point to containers, not cells or even values (2)" ;31 is $$ref, 4, "refs to arrays point to containers, not cells or even values (2)", :todo<bug>; 32 32
