123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110(**************************************************************************)(* This file is part of the Codex semantics library. *)(* *)(* Copyright (C) 2013-2025 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file LICENSE). *)(* *)(**************************************************************************)(** PPX to easily write While program in OCaml syntax *)openPpxlib(* Helper functions for integer literals and variables *)letis_integer_literalexpr=matchexpr.pexp_descwith|Pexp_constant(Pconst_integer(_,_))->true|_->falseletextract_integerexpr=matchexpr.pexp_descwith|Pexp_constant(Pconst_integer(s,_))->int_of_strings|_->Location.raise_errorf~loc:expr.pexp_loc"Expected an integer literal"letis_variableexpr=matchexpr.pexp_descwith|Pexp_ident{txt=Lident_;_}->true|_->falseletextract_variableexpr=matchexpr.pexp_descwith|Pexp_ident{txt=Lidentvar_name;_}->var_name|_->Location.raise_errorf~loc:expr.pexp_loc"Expected a variable"(* ppx_while.ml *)openPpxlibopenAst_builder.Default(* eint,estring *)openAstletint_expr~locn=[%exprInt[%eeint~locn]]letvar_expr~locv=[%exprVar(Var.of_string[%eestring~locv])]letrectranslate_aexp~loc=function|[%expr[%e?left]+[%e?right]]->[%exprAdd([%etranslate_aexp~locleft],[%etranslate_aexp~locright])]|[%expr[%e?left]-[%e?right]]->[%exprSub([%etranslate_aexp~locleft],[%etranslate_aexp~locright])]|[%expr[%e?left]*[%e?right]]->[%exprMul([%etranslate_aexp~locleft],[%etranslate_aexp~locright])]|[%expr[%e?v]]whenis_integer_literalv->int_expr~loc(extract_integerv)|[%expr[%e?v]]whenis_variablev->var_expr~loc(extract_variablev)|e->Location.raise_errorf~loc"At %a: Unknown arithmetic expression %a"Location.printlocPprintast.expressioneletrectranslate_bexp~loc=function|[%exprtrue]->[%exprTrue]|[%exprfalse]->[%exprFalse]|[%expr[%e?left]=[%e?right]]->[%exprEq([%etranslate_aexp~locleft],[%etranslate_aexp~locright])]|[%expr[%e?left]<=[%e?right]]->[%exprLe([%etranslate_aexp~locleft],[%etranslate_aexp~locright])]|[%expr[%e?left]>[%e?right]]->[%exprGt([%etranslate_aexp~locleft],[%etranslate_aexp~locright])]|[%exprnot[%e?b]]->[%exprNot[%etranslate_bexp~locb]]|[%expr[%e?left]&&[%e?right]]->[%exprAnd([%etranslate_bexp~locleft],[%etranslate_bexp~locright])]|e->Location.raise_errorf~loc"At %a: Unknown boolean expression %a"Location.printlocPprintast.expressioneletrectranslate_com~loc=function|[%exprskip]->[%exprSkip]|[%expr[%e?lhs]:=[%e?rhs]]whenis_variablelhs->[%exprAssign(Var.of_string[%eestring~loc(extract_variablelhs)],[%etranslate_aexp~locrhs])]|[%exprif[%e?cond]then[%e?tbranch]else[%e?fbranch]]->[%exprIf([%etranslate_bexp~loccond],[%etranslate_com~loctbranch],[%etranslate_com~locfbranch])]|[%exprwhile[%e?cond]do[%e?body]done]->[%exprWhile([%etranslate_bexp~loccond],[%etranslate_com~locbody])]|[%expr[%e?c1];[%e?c2]]->[%exprSeq([%etranslate_com~locc1],[%etranslate_com~locc2])]|e->Location.raise_errorf~loc"At %a: Unknown command expression %a"Location.printlocPprintast.expressione(* Register the PPX transformation *)let()=letexpr_pattern=Ast_pattern.(single_expr_payload__)inletrule=Extension.V3.declare"while_lang"Extension.Context.expressionexpr_pattern(fun~ctxtexpr->letloc=Expansion_context.Extension.extension_point_locctxtintranslate_com~locexpr)|>Context_free.Rule.extensioninDriver.register_transformation"while_lang"~rules:[rule]