@@ -0,0 +1,168 @@
1+module Effect.Memory
2+
3+import Effects
4+import Control.IOExcept
5+
6+%access public
7+
8+abstract
9+data MemoryChunk : Nat -> Nat -> Type where
10+ CH : Ptr -> MemoryChunk size initialized
11+
12+abstract
13+data RawMemory : Effect where
14+ Allocate : (n : Nat) ->
15+ RawMemory () (MemoryChunk n 0) ()
16+ Free : RawMemory (MemoryChunk n i) () ()
17+ Initialize : Bits8 ->
18+ (size : Nat) ->
19+ so (i + size <= n) ->
20+ RawMemory (MemoryChunk n i) (MemoryChunk n (i + size)) ()
21+ Peek : (offset : Nat) ->
22+ (size : Nat) ->
23+ so (offset + size <= i) ->
24+ RawMemory (MemoryChunk n i) (MemoryChunk n i) (Vect Bits8 size)
25+ Poke : (offset : Nat) ->
26+ (Vect Bits8 size) ->
27+ so (offset <= i && offset + size <= n) ->
28+ RawMemory (MemoryChunk n i) (MemoryChunk n (max i (offset + size))) ()
29+ Move : (src : MemoryChunk src_size src_init) ->
30+ (dst_offset : Nat) ->
31+ (src_offset : Nat) ->
32+ (size : Nat) ->
33+ so (dst_offset <= dst_init && dst_offset + size <= dst_size) ->
34+ so (src_offset + size <= src_init) ->
35+ RawMemory (MemoryChunk dst_size dst_init)
36+ (MemoryChunk dst_size (max dst_init (dst_offset + size))) ()
37+ GetRawPtr : RawMemory (MemoryChunk n i) (MemoryChunk n i) (MemoryChunk n i)
38+
39+private
40+do_malloc : Nat -> IOExcept String Ptr
41+do_malloc size with (fromInteger (cast size) == size)
42+ | True = do ptr <- ioe_lift $ mkForeign (FFun "malloc" [FInt] FPtr) (cast size)
43+ fail <- ioe_lift $ nullPtr ptr
44+ if fail then ioe_fail "Cannot allocate memory"
45+ else return ptr
46+ | False = ioe_fail "The target architecture does not support adressing enough memory"
47+
48+private
49+do_memset : Ptr -> Nat -> Bits8 -> Nat -> IO ()
50+do_memset ptr offset c size
51+ = mkForeign (FFun "idris_memset" [FPtr, FInt, FAny Bits8, FInt] FUnit)
52+ ptr (cast offset) c (cast size)
53+
54+private
55+do_free : Ptr -> IO ()
56+do_free ptr = mkForeign (FFun "free" [FPtr] FUnit) ptr
57+
58+private
59+do_memmove : Ptr -> Ptr -> Nat -> Nat -> Nat -> IO ()
60+do_memmove dest src dest_offset src_offset size
61+ = mkForeign (FFun "idris_memmove" [FPtr, FPtr, FInt, FInt, FInt] FUnit)
62+ dest src (cast dest_offset) (cast src_offset) (cast size)
63+
64+private
65+do_peek : Ptr -> Nat -> (size : Nat) -> IO (Vect Bits8 size)
66+do_peek _ _ O = return (Prelude.Vect.Nil)
67+do_peek ptr offset (S n)
68+ = do b <- mkForeign (FFun "idris_peek" [FPtr, FInt] FInt) ptr (cast offset)
69+ bs <- do_peek ptr (S offset) n
70+ Prelude.Monad.return (Prelude.Vect.(::) (prim__intToB8 b) bs)
71+
72+private
73+do_poke : Ptr -> Nat -> Vect Bits8 size -> IO ()
74+do_poke _ _ [] = return ()
75+do_poke ptr offset (b::bs)
76+ = do mkForeign (FFun "idris_poke" [FPtr, FInt, FAny Bits8] FUnit) ptr (cast offset) b
77+ do_poke ptr (S offset) bs
78+
79+instance Handler RawMemory (IOExcept String) where
80+ handle () (Allocate n) k
81+ = do ptr <- do_malloc n
82+ k (CH ptr) ()
83+ handle {res = MemoryChunk _ offset} (CH ptr) (Initialize c size _) k
84+ = ioe_lift (do_memset ptr offset c size) $> k (CH ptr) ()
85+ handle (CH ptr) (Free) k
86+ = ioe_lift (do_free ptr) $> k () ()
87+ handle (CH ptr) (Peek offset size _) k
88+ = do res <- ioe_lift (do_peek ptr offset size)
89+ k (CH ptr) res
90+ handle (CH ptr) (Poke offset content _) k
91+ = do ioe_lift (do_poke ptr offset content)
92+ k (CH ptr) ()
93+ handle (CH dest_ptr) (Move (CH src_ptr) dest_offset src_offset size _ _) k
94+ = do ioe_lift (do_memmove dest_ptr src_ptr dest_offset src_offset size)
95+ k (CH dest_ptr) ()
96+ handle chunk (GetRawPtr) k
97+ = k chunk chunk
98+
99+RAW_MEMORY : Type -> EFFECT
100+RAW_MEMORY t = MkEff t RawMemory
101+
102+allocate : (n : Nat) -> EffM m [RAW_MEMORY ()] [RAW_MEMORY (MemoryChunk n 0)] ()
103+allocate size = Allocate size
104+
105+initialize : {i : Nat} ->
106+ {n : Nat} ->
107+ Bits8 ->
108+ (size : Nat) ->
109+ so (i + size <= n) ->
110+ EffM m [RAW_MEMORY (MemoryChunk n i)] [RAW_MEMORY (MemoryChunk n (i + size))] ()
111+initialize c size prf = Initialize c size prf
112+
113+free : EffM m [RAW_MEMORY (MemoryChunk n i)] [RAW_MEMORY ()] ()
114+free = Free
115+
116+peek : {i : Nat} ->
117+ (offset : Nat) ->
118+ (size : Nat) ->
119+ so (offset + size <= i) ->
120+ Eff m [RAW_MEMORY (MemoryChunk n i)] (Vect Bits8 size)
121+peek offset size prf = Peek offset size prf
122+
123+poke : {n : Nat} ->
124+ {i : Nat} ->
125+ (offset : Nat) ->
126+ Vect Bits8 size ->
127+ so (offset <= i && offset + size <= n) ->
128+ EffM m [RAW_MEMORY (MemoryChunk n i)] [RAW_MEMORY (MemoryChunk n (max i (offset + size)))] ()
129+poke offset content prf = Poke offset content prf
130+
131+private
132+getRawPtr : Eff m [RAW_MEMORY (MemoryChunk n i)] (MemoryChunk n i)
133+getRawPtr = GetRawPtr
134+
135+private
136+move' : {dst_size : Nat} ->
137+ {dst_init : Nat} ->
138+ {src_init : Nat} ->
139+ (src_ptr : MemoryChunk src_size src_init) ->
140+ (dst_offset : Nat) ->
141+ (src_offset : Nat) ->
142+ (size : Nat) ->
143+ so (dst_offset <= dst_init && dst_offset + size <= dst_size) ->
144+ so (src_offset + size <= src_init) ->
145+ EffM m [RAW_MEMORY (MemoryChunk dst_size dst_init)]
146+ [RAW_MEMORY (MemoryChunk dst_size (max dst_init (dst_offset + size)))] ()
147+move' src_ptr dst_offset src_offset size dst_bounds src_bounds
148+ = Move src_ptr dst_offset src_offset size dst_bounds src_bounds
149+
150+data MoveDescriptor = Dst | Src
151+
152+move : {dst_size : Nat} ->
153+ {dst_init : Nat} ->
154+ {src_size : Nat} ->
155+ {src_init : Nat} ->
156+ (dst_offset : Nat) ->
157+ (src_offset : Nat) ->
158+ (size : Nat) ->
159+ so (dst_offset <= dst_init && dst_offset + size <= dst_size) ->
160+ so (src_offset + size <= src_init) ->
161+ EffM m [ Dst ::: RAW_MEMORY (MemoryChunk dst_size dst_init)
162+ , Src ::: RAW_MEMORY (MemoryChunk src_size src_init)]
163+ [ Dst ::: RAW_MEMORY (MemoryChunk dst_size (max dst_init (dst_offset + size)))
164+ , Src ::: RAW_MEMORY (MemoryChunk src_size src_init)] ()
165+move dst_offset src_offset size dst_bounds src_bounds
166+ = do src_ptr <- Src :- getRawPtr
167+ Dst :- move' src_ptr dst_offset src_offset size dst_bounds src_bounds
168+ return ()