(* * Neko AST for OCaml * Copyright (c)2005 Nicolas Cannasse * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type pos = { psource : string; pline : int; } type constant = | True | False | Null | This | Int of int | Float of string | String of string | Builtin of string | Ident of string | Int32 of int32 type while_flag = | NormalWhile | DoWhile type expr_decl = | EConst of constant | EBlock of expr list | EParenthesis of expr | EField of expr * string | ECall of expr * expr list | EArray of expr * expr | EVars of (string * expr option) list | EWhile of expr * expr * while_flag | EIf of expr * expr * expr option | ETry of expr * string * expr | EFunction of string list * expr | EBinop of string * expr * expr | EReturn of expr option | EBreak of expr option | EContinue | ENext of expr * expr | EObject of (string * expr) list | ELabel of string | ESwitch of expr * (expr * expr) list * expr option | ENeko of string and expr = expr_decl * pos let pos = snd let null_pos = { pline = 0; psource = "" } let mk_call v args p = ECall (v,args) , p let mk_call0 v p = ECall (v,[]) , p let mk_call1 v a p = ECall (v,[a]) , p let mk_ident i p = EConst (Ident i) , p let mk_builtin b p = EConst (Builtin b) , p let mk_int i p = EConst (Int i) , p let mk_string s p = EConst (String s) , p let mk_binop op e1 e2 p = EBinop (op,e1,e2) , p let map f (e,p) = (match e with | EBlock el -> EBlock (List.map f el) | EParenthesis e -> EParenthesis (f e) | EField (e,s) -> EField (f e, s) | ECall (e,el) -> ECall (f e, List.map f el) | EArray (e1,e2) -> EArray (f e1, f e2) | EVars vl -> EVars (List.map (fun (v,e) -> v , match e with None -> None | Some e -> Some (f e)) vl) | EWhile (e1,e2,flag) -> EWhile (f e1, f e2, flag) | EIf (e,e1,e2) -> EIf (f e, f e1, match e2 with None -> None | Some e -> Some (f e)) | ETry (e,ident,e2) -> ETry (f e, ident, f e2) | EFunction (params,e) -> EFunction (params, f e) | EBinop (op,e1,e2) -> EBinop (op, f e1, f e2) | EReturn (Some e) -> EReturn (Some (f e)) | EBreak (Some e) -> EBreak (Some (f e)) | ENext (e1,e2) -> ENext (f e1,f e2) | EObject fl -> EObject (List.map (fun (s,e) -> s , f e) fl) | ESwitch (e,cases,def) -> ESwitch (f e,List.map (fun(e1,e2) -> f e1, f e2) cases,match def with None -> None | Some e -> Some (f e)) | EReturn None | EBreak None | EContinue | ENeko _ | ELabel _ | EConst _ as x -> x) , p let iter f (e,p) = match e with | EBlock el -> List.iter f el | EParenthesis e -> f e | EField (e,s) -> f e | ECall (e,el) -> f e; List.iter f el | EArray (e1,e2) -> f e1; f e2 | EVars vl -> List.iter (fun (_,e) -> match e with None -> () | Some e -> f e) vl | EWhile (e1,e2,_) -> f e1; f e2 | EIf (e,e1,e2) -> f e; f e1; (match e2 with None -> () | Some e -> f e) | ETry (e1,_,e2) -> f e1; f e2 | EFunction (_,e) -> f e | EBinop (_,e1,e2) -> f e1; f e2 | EReturn (Some e) -> f e | EBreak (Some e) -> f e | ENext (e1,e2) -> f e1; f e2 | EObject fl -> List.iter (fun (_,e) -> f e) fl | ESwitch (e,cases,def) -> f e; List.iter (fun(e1,e2) -> f e1; f e2) cases; (match def with None -> () | Some e -> f e) | EReturn None | EBreak None | EContinue | ENeko _ | ELabel _ | EConst _ -> () let is_printable c = c >= '\032' && c <= '\126' let escape s = let b = Buffer.create (String.length s) in for i = 0 to (String.length s) - 1 do match s.[i] with | '\n' -> Buffer.add_string b "\\n" | '\t' -> Buffer.add_string b "\\t" | '\r' -> Buffer.add_string b "\\r" | '\\' -> Buffer.add_string b "\\\\" | c when c == '"' || not (is_printable c) -> Buffer.add_string b (Printf.sprintf "\\%.3d" (int_of_char c)) | c -> Buffer.add_char b c done; Buffer.contents b let s_constant = function | True -> "true" | False -> "false" | Null -> "null" | This -> "this" | Int i -> string_of_int i | Float s -> s | String s -> "\"" ^ escape s ^ "\"" | Builtin s -> "$" ^ s | Ident s -> s | Int32 i -> Int32.to_string i