diff options
Diffstat (limited to 'otherlibs/labltk/compiler')
-rw-r--r-- | otherlibs/labltk/compiler/Makefile | 36 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/compile.ml | 803 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/intf.ml | 83 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/lexer.mll | 141 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/maincompile.ml | 229 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/parser.mly | 312 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/tables.ml | 414 | ||||
-rw-r--r-- | otherlibs/labltk/compiler/tsort.ml | 72 |
8 files changed, 0 insertions, 2090 deletions
diff --git a/otherlibs/labltk/compiler/Makefile b/otherlibs/labltk/compiler/Makefile deleted file mode 100644 index 7d826a161..000000000 --- a/otherlibs/labltk/compiler/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -include ../Makefile.config - -OBJS=tsort.cmo tables.cmo lexer.cmo parser.cmo compile.cmo intf.cmo \ - maincompile.cmo - -tkcompiler : $(OBJS) - $(LABLC) $(LINKFLAGS) -o tkcompiler $(OBJS) - -lexer.ml: lexer.mll - $(LABLLEX) lexer.mll - -parser.ml parser.mli: parser.mly - $(LABLYACC) -v parser.mly - -clean : - rm -f *.cm* parser.ml parser.mli lexer.ml tkcompiler parser.output - -scratch : - rm -f *.cm* parser.ml parser.mli lexer.ml tkcompiler - -install: - cp tkcompiler $(INSTALLDIR) - -.SUFFIXES : -.SUFFIXES : .mli .ml .cmi .cmo .mlp - -.mli.cmi: - $(LABLCOMP) $(COMPFLAGS) $< - -.ml.cmo: - $(LABLCOMP) $(COMPFLAGS) $< - -depend: parser.ml parser.mli lexer.ml - $(LABLDEP) *.mli *.ml > .depend - -include .depend diff --git a/otherlibs/labltk/compiler/compile.ml b/otherlibs/labltk/compiler/compile.ml deleted file mode 100644 index dbc777da1..000000000 --- a/otherlibs/labltk/compiler/compile.ml +++ /dev/null @@ -1,803 +0,0 @@ -(* $Id$ *) - -open Tables - -(* CONFIGURE *) -(* if you set it true, ImagePhoto and ImageBitmap will annoy you... *) -let safetype = false - -let lowercase s = - let r = String.create len:(String.length s) in - String.blit s pos:0 to:r to_pos:0 len:(String.length s); - for i = 0 to String.length s - 1 - do - let c = s.[i] in - if c >= 'A' & c <= 'Z' then r.[i] <- Char.chr(Char.code c + 32) - done; - r - -let labeloff :at l = match l with - "",t -> t -| l ,t -> raise (Failure ("labeloff : " ^ l ^ " at " ^ at)) - -let labelstring l = match l with - "" -> "" -| _ -> l ^ ":" - -let labelprint :w l = w (labelstring l) - -let small s = - let sout = ref "" in - for i=0 to String.length s - 1 do - let c = - if s.[i] >= 'A' && s.[i] <= 'Z' then - Char.chr(Char.code(s.[i]) - (Char.code 'A' - Char.code 'a')) - else s.[i] - in - sout := !sout ^ (String.make len:1 c) - done; - !sout - -let small_ident s = - let idents = ["to"; "raise"; "in"; "class"; "new"] - in - let s = small s in - if List.mem elt:s idents then (String.make len:1 s.[0])^s - else s - -let gettklabel fc = - match fc.template with - ListArg( StringArg s :: _ ) -> - if (try s.[0] = '-' with _ -> false) then - String.sub s pos:1 len:(String.length s - 1) - else - if s = "" then small fc.ml_name else small s - | _ -> raise (Failure "gettklabel") - -let count elt:x l = - let count = ref 0 in - List.iter fun:(fun y -> if x = y then incr count) l; - !count - -let catenate_sep :sep = - function - [] -> "" - | x::l -> List.fold_left fun:(fun :acc s' -> acc ^ sep ^ s') acc:x l - -(* Extract all types from a template *) -let rec types_of_template = function - StringArg _ -> [] - | TypeArg (l,t) -> [l,t] - | ListArg l -> List.flatten (List.map fun:types_of_template l) - | OptionalArgs (l,tl,_) -> - begin - match List.flatten (List.map fun:types_of_template tl) with - ["",t] -> ["?"^l,t] - | [_,_] -> raise (Failure "0 label required") - | _ -> raise (Failure "0 or more than 1 args in for optionals") - end - -(* - * Pretty print a type - * used to write ML type definitions - *) -let ppMLtype ?:any{=false} ?:return{=false} ?:def{=false} ?:counter{=ref 0} = - let rec ppMLtype = - function - Unit -> "unit" - | Int -> "int" - | Float -> "float" - | Bool -> "bool" - | Char -> "char" - | String -> "string" -(* new *) - | List (Subtype (sup,sub)) -> - if return then - sub^"_"^sup^" list" - else - begin - try - let typdef = Hashtbl.find types_table key:sup in - let fcl = List.assoc key:sub typdef.subtypes in - let tklabels = List.map fun:gettklabel fcl in - let l = List.map fcl fun: - begin fun fc -> - "?" ^ begin let p = gettklabel fc in - if count elt:p tklabels > 1 then small fc.ml_name else p - end - ^ ":" ^ - let l = types_of_template fc.template in - match l with - [] -> "unit" - | [lt] -> ppMLtype (labeloff lt at:"ppMLtype") - | l -> - "(" ^ catenate_sep sep:"*" - (List.map l - fun:(fun lt -> ppMLtype (labeloff lt at:"ppMLtype"))) - ^ ")" - end in - catenate_sep sep:" ->\n" l - with - Not_found -> Printf.eprintf "ppMLtype %s/%s\n" sup sub; exit (-1) - end - | List ty -> (ppMLtype ty) ^ " list" - | Product tyl -> catenate_sep sep:" * " (List.map fun:ppMLtype tyl) - | Record tyl -> - catenate_sep sep:" * " - (List.map tyl fun:(fun (l,t) -> labelstring l ^ ppMLtype t)) - | Subtype ("widget", sub) -> sub ^ " widget" - | UserDefined "widget" -> - if any then "any widget" else - let c = String.make len:1 (Char.chr(Char.code 'a' + !counter)) - in - incr counter; - "'" ^ c ^ " widget" - | UserDefined s -> - (* a bit dirty hack for ImageBitmap and ImagePhoto *) - begin - try - let typdef = Hashtbl.find types_table key:s in - if typdef.variant then - if return then try - "[>" ^ - catenate_sep sep:"|" - (List.map typdef.constructors fun: - begin - fun c -> - "`" ^ c.var_name ^ - (match types_of_template c.template with - [] -> "" - | l -> " " ^ ppMLtype (Product (List.map l - fun:(labeloff at:"ppMLtype UserDefined")))) - end) ^ "]" - with - Not_found -> - (prerr_endline ("ppMLtype "^s^ " ?"); s) - else if not def & List.length typdef.constructors > 1 then - "#" ^ s - else s - else s - with Not_found -> s - end - | Subtype (s,s') -> s'^"_"^s - | Function (Product tyl) -> - raise (Failure "Function (Product tyl) ? ppMLtype") - | Function (Record tyl) -> - "(" ^ catenate_sep sep:" -> " - (List.map tyl fun:(fun (l,t) -> labelstring l ^ ppMLtype t)) - ^ " -> unit)" - | Function ty -> - "(" ^ (ppMLtype ty) ^ " -> unit)" - | As (_, s) -> s - in - ppMLtype - -(* Produce a documentation version of a template *) -let rec ppTemplate = function - StringArg s -> s - | TypeArg (l,t) -> "<" ^ ppMLtype t ^ ">" - | ListArg l -> "{" ^ catenate_sep sep:" " (List.map fun:ppTemplate l) ^ "}" - | OptionalArgs (l,tl,d) -> - "?" ^ l ^ "{" ^ catenate_sep sep:" " (List.map fun:ppTemplate tl) - ^ "}[<" ^ catenate_sep sep:" " (List.map fun:ppTemplate d) ^ ">]" - -let doc_of_template = function - ListArg l -> catenate_sep sep:" " (List.map fun:ppTemplate l) - | t -> ppTemplate t - -(* - * Type definitions - *) - -(* Write an ML constructor *) -let write_constructor :w {ml_name = mlconstr; template = t} = - w mlconstr; - begin match types_of_template t with - [] -> () - | l -> w " of "; - w (ppMLtype any:true (Product (List.map l - fun:(labeloff at:"write_constructor")))) - end; - w "\t\t(* tk option: "; w (doc_of_template t); w " *)" - -(* Write a rhs type decl *) -let write_constructors :w = function - [] -> fatal_error "empty type" - | x::l -> - write_constructor :w x; - List.iter l fun: - begin fun x -> - w "\n\t| "; - write_constructor :w x - end - -(* Write an ML variant *) -let write_variant :w {ml_name = mlconstr; var_name = varname; template = t} = - w "`"; - w varname; - begin match types_of_template t with - [] -> () - | l -> - w " "; - w (ppMLtype any:true def:true - (Product (List.map l fun:(labeloff at:"write_variant")))) - end; - w "\t\t(* tk option: "; w (doc_of_template t); w " *)" - -let write_variants :w = function - [] -> fatal_error "empty variants" - | x::l -> - write_variant :w x; - List.iter l fun: - begin fun x -> - w "\n | "; - write_variant :w x - end - -(* Definition of a type *) -let write_type intf:w impl:w' name def:typdef = -(* if typdef.subtypes = [] then (* If there is no subtypes *) - begin - (* The type itself *) - (* Put markers for extraction *) - w "(* type *)\n"; - w ("type "^name^" =\n\t"); - write_constructors :w (sort_components typdef.constructors); - w "\n(* /type *)\n\n" - end - else -*) - begin - if typdef.subtypes = [] then - begin - w "(* Variant type *)\n"; - w ("type "^name^" = [\n "); - write_variants :w (sort_components typdef.constructors); - w "\n]\n\n" - end - else - begin - (* Dynamic Subtyping *) - (* All the subtypes *) - List.iter typdef.subtypes fun: - begin fun (s,l) -> - w ("type "^s^"_"^name^" = [\n\t"); - write_variants w:w (sort_components l); - w ("]\n\n") - end - end - end - -(************************************************************) -(* Converters *) -(************************************************************) - -let rec converterTKtoCAML argname as:ty = - match ty with - Int -> "int_of_string " ^ argname - | Float -> "float_of_string " ^ argname - | Bool -> "(match " ^ argname ^" with - \"1\" -> true - | \"0\" -> false - | s -> Pervasives.raise (Invalid_argument (\"cTKtoCAMLbool\" ^ s)))" - | Char -> "String.get "^argname ^" 0" - | String -> argname - | UserDefined s -> "cTKtoCAML"^s^" "^argname - | Subtype ("widget",s') -> - "(Obj.magic (cTKtoCAMLwidget "^argname^") : "^s'^" widget)" - | Subtype (s,s') -> "cTKtoCAML"^s'^"_"^s^" "^argname - | List ty -> - begin match type_parser_arity ty with - OneToken -> - "(List.map (function x -> " ^ (converterTKtoCAML "x) " as:ty) - ^ argname ^ ")" - | MultipleToken -> - "iterate_converter (function x -> " ^ - (converterTKtoCAML "x) " as:ty) ^ argname ^ ")" - end - | As (ty, _) -> converterTKtoCAML argname as:ty - | t -> (prerr_endline ("ERROR with "^argname^" "^ppMLtype t);fatal_error "converterTKtoCAML") - - -(*******************************) -(* Wrappers *) -(*******************************) -let varnames :prefix n = - let rec var i = - if i > n then [] - else (prefix^(string_of_int i)) :: (var (succ i)) - in var 1 - -(* - * generate wrapper source for callbacks - * transform a function ... -> unit in a function : unit -> unit - * using primitives arg_ ... from the protocol - * Warning: sequentiality is important in generated code - * TODO: remove arg_ stuff and process lists directly ? - *) - -let rec wrapper_code fname of:ty = - match ty with - Unit -> "(function _ -> "^fname^" ())" - | As (ty, _) -> wrapper_code fname of:ty - | ty -> - "(function args ->\n\t\t" ^ - begin match ty with - Product tyl -> raise (Failure "Product -> record was done. ???") - | Record tyl -> - (* variables for each component of the product *) - let vnames = varnames prefix:"a" (List.length tyl) in - (* getting the arguments *) - let readarg = - List.map2 vnames tyl fun: - begin fun v (l,ty) -> - match type_parser_arity ty with - OneToken -> - "let ("^v^",args) = " ^ - converterTKtoCAML "(List.hd args)" as:ty ^ - ", List.tl args in\n\t\t" - | MultipleToken -> - "let ("^v^",args) = " ^ - converterTKtoCAML "args" as:ty ^ - " in\n\t\t" - end in - catenate_sep sep:"" readarg ^ fname ^ " " ^ - catenate_sep sep:" " - (List.map2 fun:(fun v (l,_) -> labelstring l^v) vnames tyl) - - (* all other types are read in one operation *) - | List ty -> - fname ^ "(" ^ converterTKtoCAML "args" as:ty ^ ")" - | String -> - fname ^ "(" ^ converterTKtoCAML "(List.hd args)" as:ty ^ ")" - | ty -> - begin match type_parser_arity ty with - OneToken -> - fname ^ "(" ^ converterTKtoCAML "(List.hd args)" as:ty ^ ")" - | MultipleToken -> - "let (v,_) = " ^ converterTKtoCAML "args" as:ty ^ - " in\n\t\t" ^ fname ^ " v" - end - end ^ ")" - -(*************************************************************) -(* Parsers *) -(* are required only for values returned by commands and *) -(* functions (table is computed by the parser) *) - -(* Tuples/Lists are Ok if they don't contain strings *) -(* they will be returned as list of strings *) - -(* Can we generate a "parser" ? - -> all constructors are unit and at most one int and one string, with null constr -*) -type parser_pieces = - { mutable zeroary : (string * string) list ; (* kw string, ml name *) - mutable intpar : string list; (* one at most, mlname *) - mutable stringpar : string list (* idem *) - } - -type mini_parser = - NoParser - | ParserPieces of parser_pieces - -let can_generate_parser constructors = - let pp = {zeroary = []; intpar = []; stringpar = []} in - if List.for_all constructors pred: - begin fun c -> - match c.template with - ListArg [StringArg s] -> - pp.zeroary <- (s,"`" ^ c.var_name):: - pp.zeroary; true - | ListArg [TypeArg(_,Int)] | ListArg[TypeArg(_,Float)] -> - if pp.intpar <> [] then false - else (pp.intpar <- ["`" ^ c.var_name]; true) - | ListArg [TypeArg(_,String)] -> - if pp.stringpar <> [] then false - else (pp.stringpar <- ["`" ^ c.var_name]; true) - | _ -> false - end - then ParserPieces pp - else NoParser - - -(* We can generate parsers only for simple types *) -(* we should avoid multiple walks *) -let write_TKtoCAML :w name def:typdef = - if typdef.parser_arity = MultipleToken then - prerr_string ("You must write cTKtoCAML" ^ name ^ - " : string list ->" ^ name ^ " * string list\n") - else - let write :consts :name = - match can_generate_parser consts with - NoParser -> - prerr_string - ("You must write cTKtoCAML" ^ name ^" : string ->"^name^"\n") - | ParserPieces pp -> - w ("let cTKtoCAML"^name^" n =\n"); - (* First check integer *) - if pp.intpar <> [] then - begin - w (" try " ^ List.hd pp.intpar ^ " (int_of_string n)\n"); - w (" with _ ->\n") - end; - w ("\tmatch n with\n"); - let first = ref true in - List.iter pp.zeroary fun: - begin fun (tk,ml) -> - if not !first then w "\t| " else w "\t"; - first := false; - w "\""; w tk; w "\" -> "; w ml; w "\n" - end; - let final = if pp.stringpar <> [] then - "n -> " ^ List.hd pp.stringpar ^ " n" - else " s -> Pervasives.raise (Invalid_argument (\"cTKtoCAML" - ^ name ^ ": \" ^s))" - in - if not !first then w "\t| " else w "\t"; - w final; - w "\n\n" - in - begin - write :name consts:typdef.constructors; - List.iter typdef.subtypes fun: begin - fun (subname,consts) -> write name:(subname^"_"^name) :consts - end - end - -(******************************) -(* Converters *) -(******************************) - -(* Produce an in-lined converter Caml -> Tk for simple types *) -(* the converter is a function of type: <type> -> string *) -let rec converterCAMLtoTK :context_widget argname as:ty = - match ty with - Int -> "TkToken (string_of_int " ^ argname ^ ")" - | Float -> "TkToken (string_of_float " ^ argname ^ ")" - | Bool -> "if "^argname^" then TkToken \"1\" else TkToken \"0\"" - | Char -> "TkToken (Char.escaped " ^ argname ^ ")" - | String -> "TkToken " ^ argname - | As (ty, _) -> converterCAMLtoTK :context_widget argname as:ty - | UserDefined s -> - let name = "cCAMLtoTK"^s^" " in - let args = argname in -(* - let args = - if is_subtyped s then (* unconstraint subtype *) - s^"_any_table "^args - else args in -*) - let args = - if requires_widget_context s then - context_widget^" "^args - else args in - name^args - | Subtype ("widget",s') -> - let name = "cCAMLtoTKwidget" in - let args = "("^argname^" : "^s'^" widget)" in -(* - let args = - if requires_widget_context s then - context_widget^" "^args - else args in -*) - name^args - | Subtype (s,s') -> - let name = "cCAMLtoTK"^s'^"_"^s^" " in - let args = if safetype then "("^argname^" : "^s'^"_"^s^")" else argname - in -(* - let args = s^"_"^s'^"_table "^argname in -*) - let args = - if requires_widget_context s then - context_widget^" "^args - else args in - name^args - | Function _ -> fatal_error "unexpected function type in converterCAMLtoTK" - | Unit -> fatal_error "unexpected unit type in converterCAMLtoTK" - | Product _ -> fatal_error "unexpected product type in converterCAMLtoTK" - | Record _ -> fatal_error "unexpected product type in converterCAMLtoTK" - | List ty -> fatal_error "unexpected list type in converterCAMLtoTK" - -(* - * Produce a list of arguments from a template - * The idea here is to avoid allocation as much as possible - * - *) - -let code_of_template :context_widget ?func:funtemplate{=false} template = - let catch_opts = ref ("","") in (* class name and first option *) - let variables = ref [] in - let variables2 = ref [] in - let varcnter = ref 0 in - let optionvar = ref None in - let newvar1 l = - match !optionvar with - Some v -> optionvar := None; v - | None -> - incr varcnter; - let v = "v" ^ (string_of_int !varcnter) in - variables := (l,v) :: !variables; v in - let newvar2 l = - match !optionvar with - Some v -> optionvar := None; v - | None -> - incr varcnter; - let v = "v" ^ (string_of_int !varcnter) in - variables2 := (l,v) :: !variables2; v in - let newvar = ref newvar1 in - let rec coderec = function - StringArg s -> "TkToken\"" ^ s ^ "\"" - | TypeArg (_,List (Subtype (sup,sub) as ty)) -> - let typdef = Hashtbl.find key:sup types_table in - let classdef = List.assoc key:sub typdef.subtypes in - let lbl = gettklabel (List.hd classdef) in - catch_opts := (sub^"_"^sup, lbl); - newvar := newvar2; - "TkTokenList (List.map fun:(function x -> " - ^ converterCAMLtoTK :context_widget "x" as:ty ^ ") opts)" - | TypeArg (l,List ty) -> - "TkTokenList (List.map fun:(function x -> " - ^ converterCAMLtoTK :context_widget "x" as:ty - ^ ") " ^ !newvar l ^ ")" - | TypeArg (l,Function tyarg) -> - "let id = register_callback " ^context_widget - ^ " callback: "^ wrapper_code (!newvar l) of:tyarg - ^ " in TkToken (\"camlcb \"^id)" - | TypeArg (l,ty) -> converterCAMLtoTK :context_widget (!newvar l) as:ty - | ListArg l -> - "TkQuote (TkTokenList [" - ^ catenate_sep sep:";\n\t" (List.map fun:coderec l) ^ "])" - | OptionalArgs (l,tl,d) -> - let nv = !newvar ("?"^l) in - optionvar := Some nv; (* Store *) - let argstr = catenate_sep sep:"; " (List.map fun:coderec tl) in - let defstr = catenate_sep sep:"; " (List.map fun:coderec d) in - "TkTokenList (match "^ nv ^" with\n" - ^ " Some " ^ nv ^ " -> [" ^ argstr ^ "]\n" - ^ " | None -> [" ^ defstr ^ "])" - in - let code = - if funtemplate then - match template with - ListArg l -> - "[|" ^ catenate_sep sep:";\n\t" (List.map fun:coderec l) ^ "|]" - | _ -> "[|" ^ coderec template ^ "|]" - else - match template with - ListArg [x] -> coderec x - | ListArg l -> - "TkTokenList [" - ^ catenate_sep sep:";\n\t" (List.map fun:coderec l) ^ "]" - | _ -> coderec template - in - code , List.rev !variables, List.rev !variables2, !catch_opts - -(* - * Converters for user defined types - *) - -(* For each case of a concrete type *) -let write_clause :w :context_widget comp = - let warrow () = - w " -> " - in - - w "`"; - w comp.var_name; - - let code, variables, variables2, (co, _) = - code_of_template :context_widget comp.template in - - (* no subtype I think ... *) - if co <> "" then raise (Failure "write_clause subtype ?"); - begin match variables with - [] -> warrow() - | [x] -> w " "; w (labeloff x at:"write_clause"); warrow() - | l -> - w " ( "; - w (catenate_sep sep:", " (List.map fun:(labeloff at:"write_clause") l)); - w ")"; - warrow() - end; - w code - - -(* The full converter *) -let write_CAMLtoTK :w def:typdef ?safetype:st{=true} name = - let write_one name constrs = - w ("let cCAMLtoTK"^name); - let context_widget = - if typdef.requires_widget_context then begin - w " w"; "w" - end - else - "dummy" in - if safetype && st then - w (" : " ^ name ^ " -> tkArgs "); - w(" = function\n\t"); - write_clause :w :context_widget (List.hd constrs); - List.iter (List.tl constrs) - fun:(fun c -> w "\n\t| "; write_clause :w :context_widget c); - w "\n\n\n" - in - if typdef.subtypes == [] then - write_one name typdef.constructors - else - List.iter typdef.subtypes fun:begin - fun (subname,constrs) -> - write_one (subname^"_"^name) constrs - end - -(* Tcl does not really return "lists". It returns sp separated tokens *) -let rec write_result_parsing :w = function - List String -> - w "(splitlist res)" - | List ty -> - w ("\tList.map fun: "^ converterTKtoCAML "(splitlist res)" as:ty) - | Product tyl -> raise (Failure "Product -> record was done. ???") - | Record tyl -> (* of course all the labels are "" *) - let rnames = varnames prefix:"r" (List.length tyl) in - w "\tlet l = splitlist res in\n"; - w ("\t if List.length l <> " ^ string_of_int (List.length tyl) ^ "\n"); - w ("\t then Pervasives.raise (TkError (\"unexpected result: \" ^ res))"); - w ("\t else "); - List.iter2 rnames tyl fun: - begin fun r (l,ty) -> - if l <> "" then raise (Failure "lables in return type!!!"); - w ("\tlet " ^ r ^ ", l = "); - begin match type_parser_arity ty with - OneToken -> - w (converterTKtoCAML "(List.hd l)" as:ty); w (", List.tl l") - | MultipleToken -> - w (converterTKtoCAML "l" as:ty) - end; - w (" in\n") - end; - w (catenate_sep sep:"," rnames) - | String -> - w (converterTKtoCAML "res" as:String) - | As (ty, _) -> write_result_parsing :w ty - | ty -> - match type_parser_arity ty with - OneToken -> w (converterTKtoCAML "res" as:ty) - | MultipleToken -> w (converterTKtoCAML "(splitlist res)" as:ty) - -let write_function :w def = - w ("let "^def.ml_name); - (* a bit approximative *) - let context_widget = match def.template with - ListArg (TypeArg(_,UserDefined("widget"))::_) -> "v1" - | ListArg (TypeArg(_,Subtype("widget",_))::_) -> "v1" - | _ -> "dummy" in - - let code, variables, variables2, (co, lbl) = - code_of_template func:true :context_widget def.template in - (* Arguments *) - let uv, lv, ov = - let rec replace_args :u :l :o = function - [] -> u, l, o - | ("",x)::ls -> - replace_args u:(x::u) :l :o ls - | (p,_ as x)::ls when p.[0] = '?' -> - replace_args :u :l o:(x::o) ls - | x::ls -> - replace_args :u l:(x::l) :o ls - in - replace_args u:[] l:[] o:[] (List.rev (variables @ variables2)) - in - List.iter (lv@ov) fun:(fun (l,v) -> w " "; w (labelstring l); w v); - if co <> "" then begin - if lv = [] && ov = [] then w (" ?" ^ lbl ^ ":eta"); - w " =\n"; - w (co ^ "_optionals"); - if lv = [] && ov = [] then w (" ?" ^ lbl ^ ":eta"); - w " (fun opts"; - if uv = [] then w " ()" - else List.iter uv fun:(fun x -> w " "; w x); - w " ->\n" - end else begin - List.iter uv fun:(fun x -> w " "; w x); - if (ov <> [] || lv = []) && uv = [] then w " ()"; - w " =\n" - end; - begin match def.result with - Unit | As (Unit, _) -> - w "tkEval "; w code; w ";()"; - | ty -> - w "let res = tkEval "; w code ; w " in \n"; - write_result_parsing :w ty; - end; - if co <> "" then w ")"; - w "\n\n" - -let write_create :w clas = - (w "let create :parent ?:name =\n" : unit); - w (" "^ clas ^ "_options_optionals (fun options () ->\n"); - w (" let w = new_atom \"" ^ clas ^ "\" :parent ?:name in\n"); - w " tkEval [|"; - w ("TkToken \"" ^ clas ^ "\";\n"); - w (" TkToken (Widget.name w);\n"); - w (" TkTokenList (List.map fun:(cCAMLtoTK" ^ clas ^ "_options dummy) options) |];\n"); - w (" w)\n\n\n") - -(* builtin-code: the file (without suffix) is in .template... *) -(* not efficient, but hell *) -let write_external :w def = - match def.template with - StringArg fname -> - let ic = open_in_bin (fname ^ ".ml") in - begin try - while true do - w (input_line ic); - w "\n" - done - with - End_of_file -> close_in ic - end - | _ -> raise (Compiler_Error "invalid external definition") - -let write_catch_optionals :w clas def:typdef = - if typdef.subtypes = [] then - (* begin Printf.eprintf "No subtypes\n";() end *) () - else - (* Printf.eprintf "Type constructors of %s\n" clas; *) - List.iter typdef.subtypes fun: - begin fun (subclass, classdefs) -> -(* - Printf.eprintf "Subclass %s" subclass; - List.iter (fun fc -> - Printf.eprintf " %s\n" fc.ml_name) classdefs; -*) - w ("let " ^ subclass ^"_"^ clas ^ "_optionals f = fun\n"); - let tklabels = List.map fun:gettklabel classdefs in - let l = - List.map classdefs fun: - begin fun fc -> - List.length (types_of_template fc.template), - types_of_template fc.template, - (* used as names of variants *) - fc.var_name, - begin let p = gettklabel fc in - if count elt:p tklabels > 1 then small fc.ml_name else p - end, - small_ident fc.ml_name (* used as labels *) - end in - let p = - List.map l fun: - begin fun (_,_,_,s,si) -> - if s = si then " ?:" ^ s - else " ?" ^ s ^ ":" ^ si - end in - let v = - List.map l fun: - begin fun (i,t,c,s,si) -> - let vars = - if i = 0 then "()" else - if i = 1 then "x" - else - let s = ref [] in - for i=1 to i do - s := !s @ ["x" ^ string_of_int i] - done; - "(" ^ catenate_sep sep:"," !s ^ ")" - in - let apvars = - if i = 0 then "" - (* VERY VERY QUICK HACK FOR 'a widget -> any widget *) - else if i = 1 && vars = "x" && t = ["",UserDefined "widget"] then - "(forget_type x)" - else vars - in - "(maycons (fun " ^ vars ^ " -> " ^ "`" ^ c ^ " " ^ apvars ^ ") " ^ si - end in - w (catenate_sep sep:"\n" p); - w " ->\n"; - w " f "; - w (catenate_sep sep:"\n " v); - w "\n []"; - w (String.make len:(List.length v) ')'); - w "\n\n" - end diff --git a/otherlibs/labltk/compiler/intf.ml b/otherlibs/labltk/compiler/intf.ml deleted file mode 100644 index 6ecb84ae2..000000000 --- a/otherlibs/labltk/compiler/intf.ml +++ /dev/null @@ -1,83 +0,0 @@ -(* $Id$ *) - -(* Write .mli for widgets *) - -open Tables -open Compile - -let write_create_p :w wname = - w "val create :\n parent:'a widget ->\n ?name:string ->\n"; - begin - try - let option = Hashtbl.find types_table key:"options" in - let classdefs = List.assoc key:wname option.subtypes in - let tklabels = List.map fun:gettklabel classdefs in - let l = List.map classdefs fun: - begin fun fc -> - begin let p = gettklabel fc in - if count elt:p tklabels > 1 then small fc.ml_name else p - end, fc.template - end in - w (catenate_sep sep:" ->\n" - (List.map l fun: - begin fun (s,t) -> - " ?" ^ s ^ ":" - ^(ppMLtype - (match types_of_template t with - [t] -> labeloff t at:"write_create_p" - | [] -> fatal_error "multiple" - | l -> Product (List.map fun:(labeloff at:"write_create_p") l))) - end)) - with Not_found -> fatal_error "in write_create_p" - end; - w (" ->\n unit -> "^wname^" widget\n"); - w " (* [create p options ?name] creates a new widget with\n"; - w " parent p and new patch component name.\n"; - w " Options are restricted to the widget class subset,\n"; - w " and checked dynamically. *)\n" - -(* Unsafe: write special comment *) -let write_function_type :w def = - if not def.safe then w "(* unsafe *)\n"; - w "val "; w def.ml_name; w " : "; - let us, ls, os = - let tys = types_of_template def.template in - let rec replace_args :u :l :o = function - [] -> u, l, o - | (_,List(Subtype _) as x)::ls -> - replace_args :u :l o:(x::o) ls - | ("",_ as x)::ls -> - replace_args u:(x::u) :l :o ls - | (p,_ as x)::ls when p.[0] = '?' -> - replace_args :u :l o:(x::o) ls - | x::ls -> - replace_args :u l:(x::l) :o ls - in - replace_args u:[] l:[] o:[] (List.rev tys) - in - let counter = ref 0 in - List.iter (ls @ os @ us) - fun:(fun (l,t) -> labelprint :w l; w (ppMLtype t :counter); w " -> "); - if (os <> [] || ls = []) && us = [] then w "unit -> "; - w (ppMLtype any:true return:true def.result); (* RETURN TYPE !!! *) - w " \n"; -(* w "(* tk invocation: "; w (doc_of_template def.template); w " *)"; *) - if def.safe then w "\n\n" - else w "\n(* /unsafe *)\n\n" - -let write_external_type :w def = - match def.template with - StringArg fname -> - let ic = open_in_bin (fname ^ ".mli") in - if not def.safe then w "(* unsafe *)\n"; - begin try - while true do - w (input_line ic); - w "\n" - done - with End_of_file -> - close_in ic; - if def.safe then w "\n\n" - else w "\n(* /unsafe *)\n\n" - end - | _ -> raise (Compiler_Error "invalid external definition") diff --git a/otherlibs/labltk/compiler/lexer.mll b/otherlibs/labltk/compiler/lexer.mll deleted file mode 100644 index 065edd3a4..000000000 --- a/otherlibs/labltk/compiler/lexer.mll +++ /dev/null @@ -1,141 +0,0 @@ -(* $Id$ *) - -{ -open Lexing -open Parser - -exception Lexical_error of string -let current_line = ref 1 - - -(* The table of keywords *) - -let keyword_table = (Hashtbl.create 149 : (string, token) Hashtbl.t) - -let _ = List.iter - fun:(fun (str,tok) -> Hashtbl.add keyword_table key:str data:tok) - [ - "int", TYINT; - "float", TYFLOAT; - "bool", TYBOOL; - "char", TYCHAR; - "string", TYSTRING; - "list", LIST; - "as", AS; - "variant", VARIANT; - "widget", WIDGET; - "option", OPTION; - "type", TYPE; - "subtype", SUBTYPE; - "function", FUNCTION; - "module", MODULE; - "external", EXTERNAL; - "sequence", SEQUENCE; - "unsafe", UNSAFE -] - - -(* To buffer string literals *) - -let initial_string_buffer = String.create len:256 -let string_buff = ref initial_string_buffer -let string_index = ref 0 - -let reset_string_buffer () = - string_buff := initial_string_buffer; - string_index := 0; - () - -let store_string_char c = - if !string_index >= String.length (!string_buff) then begin - let new_buff = String.create len:(String.length (!string_buff) * 2) in - String.blit (!string_buff) pos:0 to:new_buff to_pos:0 - len:(String.length (!string_buff)); - string_buff := new_buff - end; - String.set (!string_buff) (!string_index) c; - incr string_index - -let get_stored_string () = - let s = String.sub (!string_buff) pos:0 len:(!string_index) in - string_buff := initial_string_buffer; - s -(* To translate escape sequences *) - -let char_for_backslash = function - 'n' -> '\010' - | 'r' -> '\013' - | 'b' -> '\008' - | 't' -> '\009' - | c -> c - -let char_for_decimal_code lexbuf i = - Char.chr(100 * (Char.code(Lexing.lexeme_char lexbuf pos:i) - 48) + - 10 * (Char.code(Lexing.lexeme_char lexbuf pos:(i+1)) - 48) + - (Char.code(Lexing.lexeme_char lexbuf pos:(i+2)) - 48)) - -let saved_string_start = ref 0 - -} - -rule main = parse - '\010' { incr current_line; main lexbuf } - | [' ' '\013' '\009' '\026' '\012'] + - { main lexbuf } - | ['A'-'Z' 'a'-'z' '\192'-'\214' '\216'-'\246' '\248'-'\255' ] - ( '_' ? ['A'-'Z' 'a'-'z' '\192'-'\214' '\216'-'\246' '\248'-'\255' (*'*) '0'-'9' ] ) * - { let s = Lexing.lexeme lexbuf in - try - Hashtbl.find keyword_table key:s - with Not_found -> - IDENT s } - - | "\"" - { reset_string_buffer(); - (* Start of token is start of string. *) - saved_string_start := lexbuf.lex_start_pos; - string lexbuf; - lexbuf.lex_start_pos <- !saved_string_start; - STRING (get_stored_string()) } - | "(" { LPAREN } - | ")" { RPAREN } - | "[" { LBRACKET } - | "]" { RBRACKET } - | "{" { LBRACE } - | "}" { RBRACE } - | "," { COMMA } - | ";" { SEMICOLON } - | ":" {COLON} - | "?" {QUESTION} - | "#" { comment lexbuf; main lexbuf } - | eof { EOF } - | _ - { raise (Lexical_error("illegal character")) } - - -and string = parse - '"' - { () } - | '\\' [' ' '\010' '\013' '\009' '\026' '\012'] + - { string lexbuf } - | '\\' ['\\' '"' 'n' 't' 'b' 'r'] - { store_string_char(char_for_backslash(Lexing.lexeme_char lexbuf pos:1)); - string lexbuf } - | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] - { store_string_char(char_for_decimal_code lexbuf 1); - string lexbuf } - | eof - { raise (Lexical_error("string not terminated")) } - | '\010' - { incr current_line; - store_string_char(Lexing.lexeme_char lexbuf pos:0); - string lexbuf } - | _ - { store_string_char(Lexing.lexeme_char lexbuf pos:0); - string lexbuf } - -and comment = parse - '\010' { incr current_line } - | eof { () } - | _ { comment lexbuf } - diff --git a/otherlibs/labltk/compiler/maincompile.ml b/otherlibs/labltk/compiler/maincompile.ml deleted file mode 100644 index aa9412933..000000000 --- a/otherlibs/labltk/compiler/maincompile.ml +++ /dev/null @@ -1,229 +0,0 @@ -(* $Id$ *) - -open Tables -open Compile -open Intf - -let flag_verbose = ref false -let verbose_string s = - if !flag_verbose then prerr_string s -let verbose_endline s = - if !flag_verbose then prerr_endline s - -let input_name = ref "Widgets.src" - -let usage () = - prerr_string "Usage: tkcompiler input.src\n"; - flush stderr; - exit 1 - - -let prerr_error_header () = - prerr_string "File \""; prerr_string !input_name; - prerr_string "\", line "; - prerr_string (string_of_int !Lexer.current_line); - prerr_string ": " - - -let parse_file filename = - let ic = open_in_bin filename in - try - let lexbuf = Lexing.from_channel ic in - while true do - Parser.entry Lexer.main lexbuf - done - with - Parsing.Parse_error -> - close_in ic; - prerr_error_header(); - prerr_string "Syntax error \n"; - exit 1 - | Lexer.Lexical_error s -> - close_in ic; - prerr_error_header(); - prerr_string "Lexical error ("; - prerr_string s; - prerr_string ")\n"; - exit 1 - | Duplicate_Definition (s,s') -> - close_in ic; - prerr_error_header(); - prerr_string s; prerr_string " "; prerr_string s'; - prerr_string " is defined twice.\n"; - exit 1 - | Compiler_Error s -> - close_in ic; - prerr_error_header(); - prerr_string "Internal error: "; prerr_string s; prerr_string "\n"; - prerr_string "Please report bug\n"; - exit 1 - | End_of_file -> - close_in ic - -(* hack to provoke production of cCAMLtoTKoptions_constrs *) -let option_hack oc = - try - let typdef = Hashtbl.find types_table key:"options" in - let hack = - { parser_arity = OneToken; - constructors = - List.map typdef.constructors fun: - begin fun c -> - { component = Constructor; - ml_name = c.ml_name; - var_name = c.var_name; (* as variants *) - template = - begin match c.template with - ListArg (x::_) -> x - | _ -> fatal_error "bogus hack" - end; - result = UserDefined "options_constrs"; - safe = true } - end; - subtypes = []; - requires_widget_context = false; - variant = false } - in - write_CAMLtoTK w:(output_string to:oc) "options_constrs" def:hack safetype: false - with Not_found -> () - -let compile () = -verbose_endline "Creating tkgen.ml ..."; - let oc = open_out_bin "lib/tkgen.ml" in - let oc' = open_out_bin "lib/tkigen.ml" in - let oc'' = open_out_bin "lib/tkfgen.ml" in - let sorted_types = Tsort.sort types_order in -verbose_endline " writing types ..."; - List.iter sorted_types fun: - begin fun typname -> -verbose_string (" "^typname^" "); - try - let typdef = Hashtbl.find types_table key:typname in -verbose_string "type "; - write_type intf:(output_string to:oc) - impl:(output_string to:oc') - typname def:typdef; -verbose_string "C2T "; - write_CAMLtoTK w:(output_string to:oc') typname def:typdef; -verbose_string "T2C "; - if List.mem elt:typname !types_returned then - write_TKtoCAML w:(output_string to:oc') typname def:typdef; -verbose_string "CO "; - write_catch_optionals w:(output_string to:oc') typname def:typdef; -verbose_endline "." - with Not_found -> - if not (List.mem_assoc key:typname !types_external) then - begin - verbose_string "Type "; - verbose_string typname; - verbose_string " is undeclared external or undefined\n" - end - else verbose_endline "." - end; - option_hack oc'; -verbose_endline " writing functions ..."; - List.iter fun:(write_function w:(output_string to:oc'')) !function_table; - close_out oc; - close_out oc'; - close_out oc''; - (* Write the interface for public functions *) - (* this interface is used only for documentation *) -verbose_endline "Creating tkgen.mli ..."; - let oc = open_out_bin "lib/tkgen.mli" in - List.iter (sort_components !function_table) - fun:(write_function_type w:(output_string to:oc)); - close_out oc; -verbose_endline "Creating other ml, mli ..."; - Hashtbl.iter module_table fun: - begin fun key:wname data:wdef -> -verbose_endline (" "^wname); - let modname = wname in - let oc = open_out_bin ("lib/" ^ modname ^ ".ml") - and oc' = open_out_bin ("lib/" ^ modname ^ ".mli") in - begin match wdef.module_type with - Widget -> output_string to:oc' ("(* The "^wname^" widget *)\n") - | Family -> output_string to:oc' ("(* The "^wname^" commands *)\n") - end; - output_string to:oc "open Protocol\n"; - List.iter fun:(fun s -> output_string s to:oc; output_string s to:oc') - [ "open Tk\n"; - "open Tkintf\n"; - "open Widget\n"; - "open Textvariable\n" - ]; - begin match wdef.module_type with - Widget -> - write_create w:(output_string to:oc) wname; - write_create_p w:(output_string to:oc') wname - | Family -> () - end; - List.iter fun:(write_function w:(output_string to:oc)) - (sort_components wdef.commands); - List.iter fun:(write_function_type w:(output_string to:oc')) - (sort_components wdef.commands); - List.iter fun:(write_external w:(output_string to:oc)) - (sort_components wdef.externals); - List.iter fun:(write_external_type w:(output_string to:oc')) - (sort_components wdef.externals); - close_out oc; - close_out oc' - end; - (* write the module list for the Makefile *) - (* and hack to death until it works *) - let oc = open_out_bin "lib/modules" in - output_string to:oc "WIDGETOBJS="; - Hashtbl.iter module_table - fun:(fun key:name data:_ -> - output_string to:oc name; - output_string to:oc ".cmo "); - output_string to:oc "\n"; - Hashtbl.iter module_table - fun:(fun key:name data:_ -> - output_string to:oc name; - output_string to:oc ".ml "); - output_string to:oc ": tkgen.ml\n\n"; - Hashtbl.iter module_table fun: - begin fun key:name data:_ -> - output_string to:oc name; - output_string to:oc ".cmo : "; - output_string to:oc name; - output_string to:oc ".ml\n"; - output_string to:oc name; - output_string to:oc ".cmi : "; - output_string to:oc name; - output_string to:oc ".mli\n" - end; - close_out oc - -let main () = - Arg.parse - keywords:[ "-verbose", Arg.Unit (fun () -> flag_verbose := true), - "Make output verbose" ] - others:(fun filename -> input_name := filename) - errmsg:"Usage: tkcompiler <source file>" ; - try -verbose_string "Parsing... "; - parse_file !input_name; -verbose_string "Compiling... "; - compile (); -verbose_string "Finished"; - exit 0 - with - Lexer.Lexical_error s -> - prerr_string "Invalid lexical character: "; - prerr_endline s; - exit 1 - | Duplicate_Definition (s,s') -> - prerr_string s; prerr_string " "; prerr_string s'; - prerr_endline " is redefined illegally"; - exit 1 - | Invalid_implicit_constructor c -> - prerr_string "Constructor "; - prerr_string c; - prerr_endline " is used implicitly before defined"; - exit 1 - | Tsort.Cyclic -> - prerr_endline "Cyclic dependency of types"; - exit 1 - -let () = Printexc.catch main () diff --git a/otherlibs/labltk/compiler/parser.mly b/otherlibs/labltk/compiler/parser.mly deleted file mode 100644 index 4920c5c62..000000000 --- a/otherlibs/labltk/compiler/parser.mly +++ /dev/null @@ -1,312 +0,0 @@ -/* $Id$ */ - -%{ - -open Tables - -let lowercase s = - let r = String.create len:(String.length s) in - String.blit s pos:0 to:r to_pos:0 len:(String.length s); - let c = s.[0] in - if c >= 'A' & c <= 'Z' then r.[0] <- Char.chr(Char.code c + 32); - r - -%} - -/* Tokens */ -%token <string> IDENT -%token <string> STRING -%token EOF - -%token LPAREN /* "(" */ -%token RPAREN /* ")" */ -%token COMMA /* "," */ -%token SEMICOLON /* ";" */ -%token COLON /* ":" */ -%token QUESTION /* "?" */ -%token LBRACKET /* "[" */ -%token RBRACKET /* "]" */ -%token LBRACE /* "{" */ -%token RBRACE /* "}" */ - -%token TYINT /* "int" */ -%token TYFLOAT /* "float" */ -%token TYBOOL /* "bool" */ -%token TYCHAR /* "char" */ -%token TYSTRING /* "string" */ -%token LIST /* "list" */ - -%token AS /* "as" */ -%token VARIANT /* "variant" */ -%token WIDGET /* "widget" */ -%token OPTION /* "option" */ -%token TYPE /* "type" */ -%token SEQUENCE /* "sequence" */ -%token SUBTYPE /* "subtype" */ -%token FUNCTION /* "function" */ -%token MODULE /* "module" */ -%token EXTERNAL /* "external" */ -%token UNSAFE /* "unsafe" */ -/* Entry points */ -%start entry -%type <unit> entry - -%% -TypeName: - IDENT { lowercase $1 } - | WIDGET { "widget" } -; - -/* Atomic types */ -Type0 : - TYINT - { Int } - | TYFLOAT - { Float } - | TYBOOL - { Bool } - | TYCHAR - { Char } - | TYSTRING - { String } - | TypeName - { UserDefined $1 } -; - -/* with subtypes */ -Type1 : - Type0 - { $1 } - | TypeName LPAREN IDENT RPAREN - { Subtype ($1, $3) } - | WIDGET LPAREN IDENT RPAREN - { Subtype ("widget", $3) } - | OPTION LPAREN IDENT RPAREN - { Subtype ("options", $3) } - | Type1 AS STRING - { As ($1, $3) } -; - -/* with list constructors */ -Type2 : - Type1 - { $1 } - | Type1 LIST - { List $1 } -; - -Labeled_type2 : - Type2 - { "",$1 } - | IDENT COLON Type2 - { $1, $3 } -; - -/* products */ -Type_list : - Type2 COMMA Type_list - { $1 :: $3 } - | Type2 - { [$1] } -; - -/* records */ -Type_record : - Labeled_type2 COMMA Type_record - { $1 :: $3 } - | Labeled_type2 - { [$1] } -; - -/* callback arguments or function results*/ -FType : - LPAREN RPAREN - { Unit } - | LPAREN Type2 RPAREN - { $2 } - | LPAREN Type_record RPAREN - { Record $2 } -; - -Type : - Type2 - { $1 } - | FUNCTION FType - { Function $2 } -; - - - -SimpleArg: - STRING - {StringArg $1} - | Type - {TypeArg ("",$1) } -; - -Arg: - STRING - {StringArg $1} - | Type - {TypeArg ("",$1) } - | IDENT COLON Type - {TypeArg ($1,$3)} - | QUESTION IDENT COLON LBRACKET SimpleArgList RBRACKET DefaultList - {OptionalArgs ( $2, $5, $7 )} - | QUESTION WIDGET COLON LBRACKET SimpleArgList RBRACKET DefaultList - {OptionalArgs ( "widget", $5, $7 )} - | QUESTION IDENT COLON LBRACKET SimpleArgList RBRACKET - {OptionalArgs ( $2, $5, [] )} - | QUESTION WIDGET COLON LBRACKET SimpleArgList RBRACKET - {OptionalArgs ( "widget", $5, [] )} - | WIDGET COLON Type - {TypeArg ("widget",$3)} - | Template - { $1 } -; - -SimpleArgList: - SimpleArg SEMICOLON SimpleArgList - { $1 :: $3} - | SimpleArg - { [$1] } -; - -ArgList: - Arg SEMICOLON ArgList - { $1 :: $3} - | Arg - { [$1] } -; - -/* DefaultList Only one TypeArg in ArgList and it must be unlabeled */ -DefaultList : - LBRACKET LBRACE ArgList RBRACE RBRACKET - {$3} - -/* Template */ -Template : - LBRACKET ArgList RBRACKET - { ListArg $2 } -; - - -/* Constructors for type declarations */ -Constructor : - IDENT Template - {{ component = Constructor; - ml_name = $1; - var_name = getvarname $1 $2; - template = $2; - result = Unit; - safe = true }} - | IDENT LPAREN IDENT RPAREN Template - {{ component = Constructor; - ml_name = $1; - var_name = $3; - template = $5; - result = Unit; - safe = true }} -; - -AbbrevConstructor : - Constructor - { Full $1 } - | IDENT - { Abbrev $1 } -; - -Constructors : - Constructor Constructors - { $1 :: $2 } -| Constructor - { [$1] } -; - -AbbrevConstructors : - AbbrevConstructor AbbrevConstructors - { $1 :: $2 } -| AbbrevConstructor - { [$1] } -; - -Safe: - /* */ - { true } - | UNSAFE - { false } - -Command : - Safe FUNCTION FType IDENT Template - {{component = Command; ml_name = $4; var_name = ""; - template = $5; result = $3; safe = $1 }} -; - -External : - Safe EXTERNAL IDENT STRING - {{component = External; ml_name = $3; var_name = ""; - template = StringArg $4; result = Unit; safe = $1}} -; - -Option : - OPTION IDENT Template - {{component = Constructor; ml_name = $2; var_name = getvarname $2 $3; - template = $3; result = Unit; safe = true }} - /* Abbreviated */ -| OPTION IDENT LPAREN IDENT RPAREN Template - {{component = Constructor; ml_name = $2; var_name = $4; - template = $6; result = Unit; safe = true }} - /* Abbreviated */ -| OPTION IDENT - { retrieve_option $2 } -; - -WidgetComponents : - /* */ - { [] } - | Command WidgetComponents - { $1 :: $2 } - | Option WidgetComponents - { $1 :: $2 } - | External WidgetComponents - { $1 :: $2 } -; - -ModuleComponents : - /* */ - { [] } - | Command ModuleComponents - { $1 :: $2 } - | External ModuleComponents - { $1 :: $2 } -; - -ParserArity : - /* */ - { OneToken } - | SEQUENCE - { MultipleToken } -; - - - -entry : - TYPE ParserArity TypeName LBRACE Constructors RBRACE - { enter_type $3 $2 $5 } -| VARIANT TYPE ParserArity TypeName LBRACE Constructors RBRACE - { enter_type $4 $3 $6 variant: true } -| TYPE ParserArity TypeName EXTERNAL - { enter_external_type $3 $2 } -| SUBTYPE ParserArity OPTION LPAREN IDENT RPAREN LBRACE AbbrevConstructors RBRACE - { enter_subtype "options" $2 $5 $8 } -| SUBTYPE ParserArity TypeName LPAREN IDENT RPAREN LBRACE AbbrevConstructors RBRACE - { enter_subtype $3 $2 $5 $8 } -| Command - { enter_function $1 } -| WIDGET IDENT LBRACE WidgetComponents RBRACE - { enter_widget $2 $4 } -| MODULE IDENT LBRACE ModuleComponents RBRACE - { enter_module (lowercase $2) $4 } -| EOF - { raise End_of_file } -; diff --git a/otherlibs/labltk/compiler/tables.ml b/otherlibs/labltk/compiler/tables.ml deleted file mode 100644 index 4a606014d..000000000 --- a/otherlibs/labltk/compiler/tables.ml +++ /dev/null @@ -1,414 +0,0 @@ -(* $Id$ *) - -(* Internal compiler errors *) - -exception Compiler_Error of string -let fatal_error s = raise (Compiler_Error s) - - -(* Types of the description language *) -type mltype = - Unit - | Int - | Float - | Bool - | Char - | String - | List of mltype - | Product of mltype list - | Record of (string * mltype) list - | UserDefined of string - | Subtype of string * string - | Function of mltype (* arg type only *) - | As of mltype * string - -type template = - StringArg of string - | TypeArg of string * mltype - | ListArg of template list - | OptionalArgs of string * template list * template list - -(* Sorts of components *) -type component_type = - Constructor - | Command - | External - -(* Full definition of a component *) -type fullcomponent = { - component : component_type; - ml_name : string; (* may be no longer useful *) - var_name : string; - template : template; - result : mltype; - safe : bool - } - -let sort_components = - Sort.list order:(fun c1 c2 -> c1.ml_name < c2.ml_name) - - -(* components are given either in full or abbreviated *) -type component = - Full of fullcomponent - | Abbrev of string - -(* A type definition *) -(* - requires_widget_context: the converter of the type MUST be passed - an additional argument of type Widget. -*) - -type parser_arity = - OneToken -| MultipleToken - -type type_def = { - parser_arity : parser_arity; - mutable constructors : fullcomponent list; - mutable subtypes : (string * fullcomponent list) list; - mutable requires_widget_context : bool; - mutable variant : bool -} - -type module_type = - Widget - | Family - -type module_def = { - module_type : module_type; - commands : fullcomponent list; - externals : fullcomponent list -} - -(******************** The tables ********************) - -(* the table of all explicitly defined types *) -let types_table = (Hashtbl.create 37 : (string, type_def) Hashtbl.t) -(* "builtin" types *) -let types_external = ref ([] : (string * parser_arity) list) -(* dependancy order *) -let types_order = (Tsort.create () : string Tsort.porder) -(* Types of atomic values returned by Tk functions *) -let types_returned = ref ([] : string list) -(* Function table *) -let function_table = ref ([] : fullcomponent list) -(* Widget/Module table *) -let module_table = (Hashtbl.create 37 : (string, module_def) Hashtbl.t) - - -(* variant name *) -let rec getvarname ml_name temp = - let offhypben s = - let s = String.copy s in - if (try String.sub s pos:0 len:1 with _ -> "") = "-" then - String.sub s pos:1 len:(String.length s - 1) - else s - and makecapital s = - begin - try - let cd = s.[0] in - if cd >= 'a' && cd <= 'z' then - s.[0] <- Char.chr (Char.code cd + (Char.code 'A' - Char.code 'a')) - with - _ -> () - end; - s - in - let head = makecapital (offhypben begin - match temp with - StringArg s -> s - | TypeArg (s,t) -> s - | ListArg (h::_) -> getvarname ml_name h - | OptionalArgs (s,_,_) -> s - | ListArg [] -> "" - end) - in - let varname = if head = "" then ml_name - else if head.[0] >= 'A' && head.[0] <= 'Z' then head - else ml_name - in varname - -(***** Some utilities on the various tables *****) -(* Enter a new empty type *) -let new_type typname arity = - Tsort.add_element types_order typname; - let typdef = {parser_arity = arity; - constructors = []; - subtypes = []; - requires_widget_context = false; - variant = false} in - Hashtbl.add types_table key:typname data:typdef; - typdef - - -(* Assume that types not yet defined are not subtyped *) -(* Widget is builtin and implicitly subtyped *) -let is_subtyped s = - s = "widget" or - try - let typdef = Hashtbl.find types_table key:s in - typdef.subtypes <> [] - with - Not_found -> false - -let requires_widget_context s = - try - (Hashtbl.find types_table key:s).requires_widget_context - with - Not_found -> false - -let declared_type_parser_arity s = - try - (Hashtbl.find types_table key:s).parser_arity - with - Not_found -> - try List.assoc key:s !types_external - with - Not_found -> - prerr_string "Type "; prerr_string s; - prerr_string " is undeclared external or undefined\n"; - prerr_string ("Assuming cTKtoCAML"^s^" : string -> "^s^"\n"); - OneToken - -let rec type_parser_arity = function - Unit -> OneToken - | Int -> OneToken - | Float -> OneToken - | Bool -> OneToken - | Char -> OneToken - | String -> OneToken - | List _ -> MultipleToken - | Product _ -> MultipleToken - | Record _ -> MultipleToken - | UserDefined s -> declared_type_parser_arity s - | Subtype (s,_) -> declared_type_parser_arity s - | Function _ -> OneToken - | As (ty, _) -> type_parser_arity ty - -let enter_external_type s v = - types_external := (s,v)::!types_external - -(*** Stuff for topological Sort.list of types ***) -(* Make sure all types used in commands and functions are in *) -(* the table *) -let rec enter_argtype = function - Unit | Int | Float | Bool | Char | String -> () - | List ty -> enter_argtype ty - | Product tyl -> List.iter fun:enter_argtype tyl - | Record tyl -> List.iter tyl fun:(fun (l,t) -> enter_argtype t) - | UserDefined s -> Tsort.add_element types_order s - | Subtype (s,_) -> Tsort.add_element types_order s - | Function ty -> enter_argtype ty - | As (ty, _) -> enter_argtype ty - -let rec enter_template_types = function - StringArg _ -> () - | TypeArg (l,t) -> enter_argtype t - | ListArg l -> List.iter fun:enter_template_types l - | OptionalArgs (_,tl,_) -> List.iter fun:enter_template_types tl - -(* Find type dependancies on s *) -let rec add_dependancies s = - function - List ty -> add_dependancies s ty - | Product tyl -> List.iter fun:(add_dependancies s) tyl - | Subtype(s',_) -> if s <> s' then Tsort.add_relation types_order (s', s) - | UserDefined s' -> if s <> s' then Tsort.add_relation types_order (s', s) - | Function ty -> add_dependancies s ty - | As (ty, _) -> add_dependancies s ty - | _ -> () - -let rec add_template_dependancies s = function - StringArg _ -> () - | TypeArg (l,t) -> add_dependancies s t - | ListArg l -> List.iter fun:(add_template_dependancies s) l - | OptionalArgs (_,tl,_) -> List.iter fun:(add_template_dependancies s) tl - -(* Assumes functions are not nested in products, which is reasonable due to syntax*) -let rec has_callback = function - StringArg _ -> false - | TypeArg (l,Function _ ) -> true - | TypeArg _ -> false - | ListArg l -> List.exists pred:has_callback l - | OptionalArgs (_,tl,_) -> List.exists pred:has_callback tl - -(*** Returned types ***) -let really_add ty = - if List.mem elt:ty !types_returned then () - else types_returned := ty :: !types_returned - -let rec add_return_type = function - Unit -> () - | Int -> () - | Float -> () - | Bool -> () - | Char -> () - | String -> () - | List ty -> add_return_type ty - | Product tyl -> List.iter fun:add_return_type tyl - | Record tyl -> List.iter tyl fun:(fun (l,t) -> add_return_type t) - | UserDefined s -> really_add s - | Subtype (s,_) -> really_add s - | Function _ -> fatal_error "unexpected return type (function)" (* whoah *) - | As (ty, _) -> add_return_type ty - -(*** Update tables for a component ***) -let enter_component_types {template = t; result = r} = - add_return_type r; - enter_argtype r; - enter_template_types t - - -(******************** Types and subtypes ********************) -exception Duplicate_Definition of string * string -exception Invalid_implicit_constructor of string - -(* Checking duplicate definition of constructor in subtypes *) -let rec check_duplicate_constr allowed c = - function - [] -> false (* not defined *) - | c'::rest -> - if c.ml_name = c'.ml_name then (* defined *) - if allowed then - if c.template = c'.template then true (* same arg *) - else raise (Duplicate_Definition ("constructor",c.ml_name)) - else raise (Duplicate_Definition ("constructor", c.ml_name)) - else check_duplicate_constr allowed c rest - -(* Retrieve constructor *) -let rec find_constructor cname = function - [] -> raise (Invalid_implicit_constructor cname) - | c::l -> if c.ml_name = cname then c - else find_constructor cname l - -(* Enter a type, must not be previously defined *) -let enter_type typname ?:variant{=false} arity constructors = - try - Hashtbl.find types_table key:typname; - raise (Duplicate_Definition ("type", typname)) - with Not_found -> - let typdef = new_type typname arity in - if variant then typdef.variant <- true; - List.iter constructors fun: - begin fun c -> - if not (check_duplicate_constr false c typdef.constructors) - then begin - typdef.constructors <- c :: typdef.constructors; - add_template_dependancies typname c.template - end; - (* Callbacks require widget context *) - typdef.requires_widget_context <- - typdef.requires_widget_context or - has_callback c.template - end - -(* Enter a subtype *) -let enter_subtype typ arity subtyp constructors = - (* Retrieve the type if already defined, else add a new one *) - let typdef = - try Hashtbl.find types_table key:typ - with Not_found -> new_type typ arity - in - if List.mem_assoc key:subtyp typdef.subtypes - then raise (Duplicate_Definition ("subtype", typ ^" "^subtyp)) - else begin - let real_constructors = - List.map constructors fun: - begin function - Full c -> - if not (check_duplicate_constr true c typdef.constructors) - then begin - add_template_dependancies typ c.template; - typdef.constructors <- c :: typdef.constructors - end; - typdef.requires_widget_context <- - typdef.requires_widget_context or - has_callback c.template; - c - | Abbrev name -> find_constructor name typdef.constructors - end - in - (* TODO: duplicate def in subtype are not checked *) - typdef.subtypes <- - (subtyp , Sort.list real_constructors - order:(fun c1 c2 -> c1.var_name <= c2.var_name)) :: - typdef.subtypes - end - -(******************** Widgets ********************) -(* used by the parser; when enter_widget is called, - all components are assumed to be in Full form *) -let retrieve_option optname = - let optiontyp = - try Hashtbl.find types_table key:"options" - with - Not_found -> raise (Invalid_implicit_constructor optname) - in find_constructor optname optiontyp.constructors - -(* Sort components by type *) -let rec add_sort acc:l obj = - match l with - [] -> [obj.component ,[obj]] - | (s',l)::rest -> - if obj.component = s' then - (s',obj::l)::rest - else - (s',l)::(add_sort acc:rest obj) - -let separate_components = List.fold_left fun:add_sort acc:[] - -let enter_widget name components = - try - Hashtbl.find module_table key:name; - raise (Duplicate_Definition ("widget/module", name)) - with Not_found -> - let sorted_components = separate_components components in - List.iter sorted_components fun: - begin function - Constructor, l -> - enter_subtype "options" MultipleToken - name (List.map fun:(fun c -> Full c) l) - | Command, l -> - List.iter fun:enter_component_types l - | External, _ -> () - end; - let commands = - try List.assoc key:Command sorted_components - with Not_found -> [] - and externals = - try List.assoc key:External sorted_components - with Not_found -> [] - in - Hashtbl.add module_table key:name - data:{module_type = Widget; commands = commands; externals = externals} - -(******************** Functions ********************) -let enter_function comp = - enter_component_types comp; - function_table := comp :: !function_table - - -(******************** Modules ********************) -let enter_module name components = - try - Hashtbl.find module_table key:name; - raise (Duplicate_Definition ("widget/module", name)) - with Not_found -> - let sorted_components = separate_components components in - List.iter sorted_components fun: - begin function - Constructor, l -> fatal_error "unexpected Constructor" - | Command, l -> List.iter fun:enter_component_types l - | External, _ -> () - end; - let commands = - try List.assoc key:Command sorted_components - with Not_found -> [] - and externals = - try List.assoc key:External sorted_components - with Not_found -> [] - in - Hashtbl.add module_table key:name - data:{module_type = Family; commands = commands; externals = externals} - diff --git a/otherlibs/labltk/compiler/tsort.ml b/otherlibs/labltk/compiler/tsort.ml deleted file mode 100644 index b82028924..000000000 --- a/otherlibs/labltk/compiler/tsort.ml +++ /dev/null @@ -1,72 +0,0 @@ -(* $Id$ *) - -(* Topological Sort.list *) -(* d'apres More Programming Pearls *) - -(* node * pred count * successors *) - -type 'a entry = - {node : 'a; - mutable pred_count : int; - mutable successors : 'a entry list - } - -type 'a porder = 'a entry list ref - -exception Cyclic - -let find_entry order node = - let rec search_entry = - function - [] -> raise Not_found - | x::l -> if x.node = node then x else search_entry l - in - try - search_entry !order - with - Not_found -> let entry = {node = node; - pred_count = 0; - successors = []} in - order := entry::!order; - entry - -let create () = ref [] - -(* Inverted args because Sort.list builds list in reverse order *) -let add_relation order (succ,pred) = - let pred_entry = find_entry order pred - and succ_entry = find_entry order succ in - succ_entry.pred_count <- succ_entry.pred_count + 1; - pred_entry.successors <- succ_entry::pred_entry.successors - -(* Just add it *) -let add_element order e = - find_entry order e; - () - -let sort order = - let q = Queue.create () - and result = ref [] in - List.iter !order - fun:(function {pred_count = n} as node -> - if n = 0 then Queue.add node q); - begin try - while true do - let t = Queue.take q in - result := t.node :: !result; - List.iter t.successors fun: - begin fun s -> - let n = s.pred_count - 1 in - s.pred_count <- n; - if n = 0 then Queue.add s q - end - done - with - Queue.Empty -> - List.iter !order - fun:(fun node -> if node.pred_count <> 0 - then raise Cyclic) - end; - !result - - |