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
------------------------------------------------------------------------------ 
--- Library for converting ground terms to strings and vice versa. 
---
--- Remark: The `Data` type class constraint is removed for KiCS2
--- since this causes a memory leak (due to the non-deterministic method
--- `aValue`) but it is not used in the implementation.
--- 
--- @author Michael Hanus 
--- @version October 2024
------------------------------------------------------------------------------ 
{-# LANGUAGE CPP #-}

module ReadShowTerm ( showTerm, readsUnqualifiedTerm, readUnqualifiedTerm )
 where

import Data.Char ( isSpace )

--- Transforms a ground(!) data term into a string representation
--- in standard prefix notation. 
--- Thus, `showTerm` suspends until its argument is ground.
--- This function is similar to the prelude function `show`
--- but can read the string back with `readUnqualifiedTerm`
--- (provided that the constructor names are unique without the module
--- qualifier).



showTerm :: Data a => a -> String

showTerm x = prim_showTerm $## x

prim_showTerm :: _ -> String
prim_showTerm external


--- Transform a string containing a data term in standard prefix notation 
--- without module qualifiers into the corresponding data term. 
--- The first argument is a non-empty list of module qualifiers
--- that are tried to prefix the constructor in the string
--- in order to get the qualified constructors 
--- (that must be defined in the current program!). 
--- In case of a successful parse, the result is a one element list 
--- containing a pair of the data term and the remaining unparsed string. 




readsUnqualifiedTerm :: Data a => [String] -> String -> [(a,String)]

readsUnqualifiedTerm [] _ =
  error "ReadShowTerm.readsUnqualifiedTerm: list of module prefixes is empty"
readsUnqualifiedTerm (prefix:prefixes) s =
  readsUnqualifiedTermWithPrefixes (prefix:prefixes) s




readsUnqualifiedTermWithPrefixes :: Data a => [String] -> String -> [(a,String)]

readsUnqualifiedTermWithPrefixes prefixes s =
  (prim_readsUnqualifiedTerm $## prefixes) $## s

prim_readsUnqualifiedTerm :: [String] -> String -> [(_,String)]
prim_readsUnqualifiedTerm external

--- Transforms a string containing a data term in standard prefix notation 
--- without module qualifiers into the corresponding data term. 
--- The first argument is a non-empty list of module qualifiers
--- that are tried to prefix the constructor in the string
--- in order to get the qualified constructors 
--- (that must be defined in the current program!). 
--- 
--- Example: `readUnqualifiedTerm ["Prelude"] "Just 3"` evaluates to `(Just 3)`




readUnqualifiedTerm :: Data a => [String] -> String -> a

readUnqualifiedTerm prefixes s = case result of
  [(term,tail)]
     -> if all isSpace tail
          then term
          else error $ "ReadShowTerm.readUnqualifiedTerm: no parse, " ++
                       "unmatched string after term: " ++ tail
  [] ->  error "ReadShowTerm.readUnqualifiedTerm: no parse"
  _  ->  error "ReadShowTerm.readUnqualifiedTerm: ambiguous parse"
 where
  result = readsUnqualifiedTerm prefixes s