blob: ffa3a17de6c1d4b57ea36f58864a13a8d880cc00 [file] [log] [blame] [edit]
-- A first attempt at translating the minimal C example: brutal.c
-- We use abstract functions to hide the pointer arithmetic and
-- iteration required by the example. The rest of the example can
-- be expressed in Cogent.
include <gum/common/common.cogent>
include <gum/common/iterator.cogent>
type Stuff = {
a : U32,
b : U32,
c : U32
}
type Entry = {
len : U32,
stuff : #Stuff,
name : CString -- an abstraction over char pointer; closest equivalent
-- to flexible array member.
}
type EntryBlock
type CString
get_block : (SysState) -> (SysState, EntryBlock!)
get_entry_at_offset : (EntryBlock!, U64) -> Entry!
is_entry : (EntryBlock!, Entry!) -> Bool
cstring_cmp : (CString!, CString!) -> Bool
stuff_ptr : (Entry!) -> Stuff!
gen_next_entry : #{ acc : U64, obsv : (EntryBlock!, CString!) } ->
GeneratorResult Entry! Stuff! () U64
gen_next_entry #{ acc = offset , obsv = (block, _) } =
let e = get_entry_at_offset(block, offset)
and new_offset = offset + upcast e.len in
if is_entry (block, e) then (new_offset, Yield e)
else (offset, Stop ())
cons_next_entry : #{ obj : Entry!, acc : U64, obsv : (EntryBlock!, CString!) } ->
ConsumerResult Stuff! () U64
cons_next_entry #{obj = e, acc = offset, obsv = (block, needle)} =
if e.len == 0 then (offset, Stop ())
else if cstring_cmp(needle, e.name) then (offset, Return (stuff_ptr e))
else (offset, Next)
findStuff : (SysState, CString!) -> (SysState, Option Stuff!)
findStuff (sys, needle) =
let (sys, block) = get_block(sys)
and (_, res) = iterate [Entry!, Stuff!, (), U64 , (EntryBlock!, CString!)]
#{ gen = gen_next_entry
, cons = cons_next_entry
, acc = 0
, obsv = (block, needle) }
in res
| Return s -> (sys, Some s)
| Stop () -> (sys, None)