| None ->
None
-let maybe f x = try Some (f x) with _ -> None
+let maybe f x = try Some (f x) with Not_found -> None
let tee f x = try ignore @@ f x; x with _ -> x
type ('a,'b) either = Val of 'a | Err of 'b
OCAMLINCLUDES += $(absname type/)
OCAML_LIBS += $(absname type/type)
-.SUBDIRS: parser checker codegen
+.SUBDIRS: parser filter codegen
UseCamlp4(pa_oo)
interCode
parser
codegen
- checker
+ filter
PROGRAM = habc-scm
+++ /dev/null
-let check table program =
- Binding.check table program
UseCamlp4(pa_openin pa_oo)
FILES[] =
- scope
module
binding
closureTrans
let to_bytes program =
program
- +> Scope.trans
+(* +> Scope.trans*)
+> Module.of_ast
+> ClosureTrans.trans
+> Binding.of_module
+++ /dev/null
-open Base
-type qname = (string list * string)
-
-type env = {
- binding: qname list
-}
-
-let empty = {
- binding = []
-}
-
-let sname x =
- ([],x)
-
-let add env x =
- {binding = x @ env.binding}
-
-let find_qname current (ns,name) {binding=binding} =
- try
- current
- +> HList.scanl (fun x y -> x @ [y] ) []
- +> List.map (fun ns' -> (ns' @ ns, name))
- +> List.find (fun qname -> List.mem qname binding)
- with Not_found ->
- (ns,name)
-
-let expr_scope current env (expr : Ast.expr') : Ast.expr' =
- (Ast.fix_fold Ast.fold)
- begin fun env ->
- function
- `Lambda (args,_) ->
- args
- +> List.map (sname $ Node.value)
- +> add env
- | `Let (decls,_) | `LetRec (decls,_) ->
- decls
- +> List.map (sname $ Node.value $ fst)
- +> add env
- | `Int _ | `String _ | `Bool _ | `Float _ | `Var _ | `Call _
- | `If _ | `Block _ | `New _ | `Invoke _ | `SlotRef _ | `SlotSet _ ->
- env
- end
- begin fun env ->
- function
- `Var var ->
- `Var {var with Node.value = find_qname current var.Node.value env}
- | `Lambda _ | `Let _ | `LetRec _ | `Int _ | `String _ | `Bool _
- | `Float _ | `Call _ | `If _ | `Block _ | `New _ | `Invoke _
- | `SlotRef _ | `SlotSet _ as e ->
- e
- end
- env expr
-
-let method_scope current env m =
- let env' =
- m.Ast.args
- +> List.map (sname $ Node.value)
- +> add env in
- {m with Ast.body = expr_scope current env' m.Ast.body}
-
-let rec stmt_scope (current,env) =
- function
- `Define (name,body) ->
- let env' =
- add env [(current,Node.value name)] in
- (current,env'), `Define(name,expr_scope current env' body)
- | `Class c ->
- let env' =
- add env [(current, Node.value c.Ast.class_name)] in
- let methods' =
- List.map (method_scope current env') c.Ast.methods in
- (current,env'), `Class {c with
- Ast.methods = methods'}
- | `Expr expr ->
- (current,env),`Expr (expr_scope current env expr)
- | `Module m ->
- let current' =
- current @ [Node.value @@ m.Ast.module_name] in
- (current',env),`Module {m with Ast.stmts = snd @@ map_accum_left stmt_scope (current',env) m.Ast.stmts}
-
-let trans s =
- snd @@ map_accum_left stmt_scope ([],empty) s
-
-
+++ /dev/null
-val trans : Ast.program -> Ast.program
#load "type.cma";;
#load "checker.cma";;
-#load "../../../camlp4/pa_oo.cmo";;
\ No newline at end of file
+#load "../../../camlp4/pa_oo.cmo";;
+#load "../../../camlp4/pa_openin.cmo";;
\ No newline at end of file
OCAMLPACKS[] = extlib
-UseCamlp4(pa_oo)
+UseCamlp4(pa_oo pa_openin)
FILES[] =
binding
main
-PROGRAM = ../checker
+PROGRAM = ../filter
OCAMLOPT = ocamlopt -for-pack $(capitalize $(basename $(PROGRAM)))
OCAMLOPTLINK = ocamlopt
OCamlPackage($(PROGRAM), $(FILES))
-OCamlLibrary(checker, $(FILES))
+OCamlLibrary(filter, $(FILES))
.DEFAULT: $(PROGRAM).cmo
| None ->
table#mem_symbol var.value
-let check_access env ({ value = (ns,name)} as var) =
+let bind_qname env ({ value = (ns,name)} as var) =
env.current
+> HList.scanl (fun x y -> x @ [y] ) []
+> List.map (fun ns' -> {var with value=(ns' @ ns, name)})
- +> List.exists (is_access env)
- +> (fun b -> if not b then raise (Unbound_var var))
-
-let check_expr env expr =
- ignore @@ Ast.fix_fold Ast.fold
- (fun env expr ->
- match expr with
- | `Var var ->
- check_access env var;
- env
- | `New (klass,_) ->
- check_access env klass;
- env
- | `Let (decls,_) | `LetRec (decls,_) ->
- add_local (List.map fst decls) env
- | `Lambda (args,_) ->
- add_local args env
- | `Invoke (_,meth,_) ->
- if not( MSet.mem meth env.meths ) &&
- not( env.table#mem_method meth.value ) then
- raise (Unbound_method meth)
- else
- env
- | #Ast.expr ->
- env)
- const env expr
+ +> maybe (List.find (is_access env))
+ +> function Some c -> c | None -> raise (Unbound_var var)
+
+let bind_expr env expr =
+ Ast.fix_fold Ast.fold
+ begin fun env -> function
+ | `Let (decls,_) | `LetRec (decls,_) ->
+ add_local (List.map fst decls) env
+ | `Lambda (args,_) ->
+ add_local args env
+ | #Ast.expr ->
+ env end
+ begin fun env -> function
+ | `Var var ->
+ `Var (bind_qname env var)
+ | `New (c,args) ->
+ `New (bind_qname env c,args)
+ | `Invoke (_,meth,_) as expr ->
+ if not( MSet.mem meth env.meths ) &&
+ not( env.table#mem_method meth.value ) then
+ raise (Unbound_method meth)
+ else
+ expr
+ | #Ast.expr as e ->
+ e end
+ env expr
let add_var var exports env =
let access =
{env with
meths = List.fold_left (flip MSet.add) env.meths methods}
-let rec check_stmt exports env =
- function
- `Module {Ast.module_name = {Node.value=name};
- exports = exports;
- stmts = body} ->
+let rec bind_stmt exports env stmt =
+ open Ast in
+ match stmt with
+ `Module ({module_name = {Node.value=name};
+ exports = exports;
+ stmts = stmts} as m) ->
let env' =
{env with current =
env.current @ [name] } in
- let env'' =
- List.fold_left (check_stmt exports) env' body in
- {env'' with current = env.current}
+ let env'', stmts' =
+ map_accum_left (bind_stmt exports) env' stmts in
+ ({env'' with current = env.current},
+ `Module {m with stmts = stmts'})
| `Expr expr ->
- check_expr env expr;
- env
- | `Define ({Node.value=name},expr) ->
+ env, `Expr (bind_expr env expr)
+ | `Define ({Node.value=name} as node, expr) ->
let env' =
add_var name exports env in
- check_expr env' expr;
- env'
- | `Class {Ast.class_name={Node.value=klass};
- super=super;
- methods=methods} ->
- check_access env super;
+ env', `Define(node,bind_expr env' expr)
+ | `Class ({class_name={Node.value=klass};
+ super=super;
+ methods=methods} as c) ->
let env' =
add_methods (List.map
- (function {Ast.method_name=`Public m} | {Ast.method_name=`Static m} ->
+ (function {method_name=`Public m} | {method_name=`Static m} ->
m) methods) @@
add_var klass exports env in
- List.iter (fun {Ast.args=args; body=body} ->
- check_expr (add_local args env') body)
- methods;
- env'
+ let methods' =
+ List.map (fun m ->
+ {m with body = bind_expr (add_local m.args env') m.body})
+ methods in
+ env',`Class {c with
+ super = bind_qname env super;
+ methods = methods'}
-let check table program =
+let bind table program =
let env = {
- meths = MSet.empty;
- vars = [];
+ meths = MSet.empty;
+ vars = [];
current = [];
- table = (table :> table) } in
- ignore @@
- List.fold_left (check_stmt `All) env program;
- program
+ table = (table :> table) } in
+ snd @@ map_accum_left (bind_stmt `All) env program
+
method mem_method : string -> bool
end
-val check : #table -> Ast.program -> Ast.program
+val bind : #table -> Ast.program -> Ast.program
--- /dev/null
+let filter table program =
+ Binding.bind table program
Parser.Parsec.Syntax_error loc ->
error "synatx error" loc;
exit 1
- | Checker.Binding.Unbound_var ({Node.value=(ns,name)} as loc) ->
+ | Filter.Binding.Unbound_var ({Node.value=(ns,name)} as loc) ->
let name =
String.concat "." @@ ns @ [name] in
error ("unbound variable") {loc with Node.value = name};
exit 1
- | Checker.Binding.Unbound_method loc ->
+ | Filter.Binding.Unbound_method loc ->
error ("unbound method") loc;
exit 1
input
+> Node.of_file
+> Parser.Main.parse table
- +> Checker.Main.check table
let find includes file =
try
InterCode.add (module_name input) (to_ast extern input) table
end InterCode.empty
+> (fun table -> table#to_ast)
+ +> Filter.Main.filter extern
+> Codegen.Main.output (open_out_bin output)
let compile table input output =
input
+> to_ast table
+ +> Filter.Main.filter table
+> (fun program -> InterCode.add (module_name output) program table)
+> InterCode.output (module_name output) (file output ".ho")
OCAML_LIBS += $(SRC)/type/type
-.SUBDIRS: codegen checker type parser
+.SUBDIRS: codegen filter type parser
OCAMLINCLUDES += $(SRC)
################################################
revListTest
asmTest
astUtil
- scopeTest
closureTransTest
codegenExprTest
codegenStmtTest
+++ /dev/null
-open Base
-open Ast
-open Scope
-open AstUtil
-open OUnit
-
-let ok x y =
- OUnit.assert_equal ~printer:Std.dump
- x (Scope.trans y)
-
-let any = block []
-let _ =
- ("scope.ml" >::: [
- "expr" >::
- (fun () ->
- ok
- [foo_mod [ define "x" any;
- expr (var ["foo"] "x")]]
- [foo_mod [ define "x" any;
- expr (var [] "x")]]);
- "expr(unbound)" >::
- (fun () ->
- ok
- [foo_mod [ define "x" any;
- expr (var [] "y")]]
- [foo_mod [ define "x" any;
- expr (var [] "y")]]);
- "expr(not module)" >::
- (fun () ->
- ok
- [foo_mod [ define "x" any];
- expr (var ["foo"] "x")]
- [foo_mod [ define "x" any];
- expr (var ["foo"] "x")]);
- "define" >::
- (fun () ->
- ok
- [foo_mod [ define "x" @@ var ["foo"] "x" ]]
- [foo_mod [ define "x" @@ var [] "x" ]]);
- "class" >::
- (fun () ->
- let c expr =
- class_ (Node.ghost "Foo")
- (Node.ghost ([],"Object")) []
- [public_meth "f" [] expr] in
- ok
- [foo_mod [ define "x" any;
- c (var ["foo"] "x")]]
- [foo_mod [ define "x" any;
- c (var [] "x")]])
- ]) +> run_test_tt
-
PROGRAM = runner
-OCAMLINCLUDES += $(SRC)/checker
-OCAML_LIBS += $(SRC)/checker/checker
+OCAMLINCLUDES += $(SRC)/filter
+OCAML_LIBS += $(SRC)/filter/filter
OCamlProgram($(PROGRAM), $(FILES))
method mem_method name = false
end
+let ok x y =
+ OUnit.assert_equal ~printer:Std.dump
+ x (Binding.bind table y)
+
+let any = block []
+
let ok_s program =
- ignore @@ Binding.check table program
+ ignore @@ Binding.bind table program
let ok_e expr =
ok_s [`Expr expr]
let ng_s exn s =
assert_raises exn
(fun () ->
- ignore @@ Binding.check empty s)
+ ignore @@ Binding.bind empty s)
let ng_e exn xs =
ng_s exn [`Expr xs]
define "x" @@ block []
];
expr (var ["bar"] "x")]]);
- "internal should be accessed from inner moudle" >::
+ "internal" >::
(fun () ->
ok_s [AstUtil.module_ "foo" (`Only []) [
define "x" @@ block [];
expr (var ["foo"] "x")]]);
- "internal should not access from outter-moudle" >::
+ "internal(borbidden)" >::
(fun () ->
ng_s (Forbidden_var (qname ["foo"] "x"))
[AstUtil.module_ "foo" (`Only []) [
ok_e ( lambda ["x"; "y"] (var [] "x"));
ok_e ( lambda ["x"; "y"] (var [] "y")));
];
+ "binding" >::: [
+ "expr" >::
+ (fun () ->
+ ok
+ [foo_mod [ define "x" any;
+ expr (var ["foo"] "x")]]
+ [foo_mod [ define "x" any;
+ expr (var [] "x")]]);
+ "expr(not module)" >::
+ (fun () ->
+ ok
+ [foo_mod [ define "x" any];
+ expr (var ["foo"] "x")]
+ [foo_mod [ define "x" any];
+ expr (var ["foo"] "x")]);
+ "define" >::
+ (fun () ->
+ ok
+ [foo_mod [ define "x" @@ var ["foo"] "x" ]]
+ [foo_mod [ define "x" @@ var [] "x" ]]);
+ "class" >::
+ (fun () ->
+ let c expr =
+ class_ "Foo" (["std"],"Object") []
+ [public_meth "f" [] expr] in
+ ok
+ [foo_mod [ define "x" any;
+ c (var ["foo"] "x")]]
+ [foo_mod [ define "x" any;
+ c (var [] "x")]])];
]) +> run_test_tt