ООП в Окамле

class mapper = object(self) method map_code code = List.map self#map_stmt code method map_stmt = function | Break | DefVar _ as x -> x | Assign(lv, rv) -> Assign(self#map_lvalue lv, self#map_rvalue rv) | Call(name, rvs) -> Call(name, List.map self#map_rvalue rvs) | Comp code -> Comp(self#map_code code) ... method map_lvalue = function ... method map_rvalue = function ... method map_cond = function ... end
Например, замена переменных по переданному набору имя-значение выглядит так:
let subst_vars smap code = let o = object inherit mapper as super method map_lvalue = function | Var name as x -> (try M.find name smap with Not_found -> x) | something_else -> super#map_lvalue something_else end in o#map_code code
Тут создается объект неназванного типа, унаследованного от класса mapper, в нем переопределен один метод, а в нем фактически переопределен только один вариант АТД, все остальное делает базовый класс, рекурсивно проходя по всем закоулкам и вариантам дерева. Это можно еще упростить. Например, для трансформации стейтментов была добавлена такая функция:
let subst_code_by_stmt f code = let o = object inherit mapper as super method map_stmt st = match f st with Some st' -> st' | None -> super#map_stmt st end in o#map_code code
Использование которой для совершения конкретной трансформации сводится вообще к одной строчке:
C.subst_code_by_stmt (function C.Print x -> Some(C.Prchar x) | _ -> None) code
Кажется, без ООП так просто не получилось бы.
|
</> |