1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798(** A value identifier*)typeide=string[@@derivingshow](** The type representing Abstract Syntax Tree expressions *)typeexpr=|Unit|Integerofint|Booleanofbool|Symbolofide|Listoflist_pattern(* List operations *)|Headofexpr|Tailofexpr|Consofexpr*expr(* Numerical Operations *)|Sumofexpr*expr|Subofexpr*expr|Multofexpr*expr|Eqofexpr*expr|Gtofexpr*expr|Ltofexpr*expr(* Boolean operations *)|Andofexpr*expr|Orofexpr*expr|Notofexpr(* Control flow and functions *)|IfThenElseofexpr*expr*expr|Letofide*expr*expr|Letlazyofide*expr*expr|Letrecofide*expr*expr|Letreclazyofide*expr*expr|Lambdaofidelist*expr|Applyofexpr*exprlist[@@derivingshow{with_path=false}]andlist_pattern=EmptyList|ListValueofexpr*list_pattern[@@derivingshow{with_path=false}](** A type to build lists, mutually recursive with `expr` *)(** A purely functional environment type, parametrized *)type'aenv_t=(string*'a)list[@@derivingshow{with_path=false}](** A type that represents an evaluated (reduced) value *)typeevt=|EvtUnit|EvtIntofint|EvtBoolofbool|EvtListofevtlist|Closureofidelist*expr*(type_wrapperenv_t)(** RecClosure keeps the function name in the constructor for recursion *)|RecClosureofide*idelist*expr*(type_wrapperenv_t)[@@derivingshow{with_path=false}]andtype_wrapper=|LazyExpressionofexpr|AlreadyEvaluatedofevt[@@derivingshow](** Wrapper type that allows both AST expressions and
evaluated expression for lazy evaluation *)letrecshow_unpacked_evte=matchewith|EvtIntv->string_of_intv|EvtBoolv->string_of_boolv|EvtListl->"["^(String.concat"; "(List.mapshow_unpacked_evtl))^"]"|Closure(params,_,_)->"(fun "^(String.concat" "params)^" -> ... )"|RecClosure(name,params,_,_)->name^" = (rec fun "^(String.concat" "params)^" -> ... )"|_->show_evte(** An environment of already evaluated values *)typeenv_type=type_wrapperenv_t(** A recursive type representing a stacktrace frame *)typestackframe=|StackValueofint*expr*stackframe|EmptyStack[@@derivingshow{with_path=false}](** Convert a native list to an AST list *)letrecexpand_listl=matchlwith|[]->EmptyList|x::xs->ListValue(x,expand_listxs)(** Push an AST expression into a stack
@param s The stack where to push the expression
@param e The expression to push
*)letpush_stack(s:stackframe)(e:expr)=matchswith|StackValue(d,ee,ss)->StackValue(d+1,e,StackValue(d,ee,ss))|EmptyStack->StackValue(1,e,EmptyStack)(** Pop an AST expression from a stack *)letpop_stack(s:stackframe)=matchswith|StackValue(_,_,ss)->ss|EmptyStack->failwith"Stack underflow"exceptionUnboundVariableofstringexceptionWrongBindListexceptionTypeErrorofstringexceptionListErrorofstringexceptionSyntaxErrorofstring