Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #use "semantic-analyser.ml";;
- (* This module is here for you convenience only!
- You are not required to use it.
- you are allowed to change it. *)
- module type CODE_GEN = sig
- (* This signature assumes the structure of the constants table is
- a list of key-value pairs:
- - The keys are constant values (Sexpr(x) or Void)
- - The values are pairs of:
- * the offset from the base const_table address in bytes; and
- * a string containing the byte representation (or a sequence of nasm macros)
- of the constant value
- For example: [(Sexpr(Nil), (1, "SOB_NIL"))]
- *)
- (* val make_consts_tbl : expr' list -> (string * (constant * int)) list *)
- val make_consts_tbl : expr' list -> (constant * (int * string)) list
- (* This signature assumes the structure of the fvars table is
- a list of key-value pairs:
- - The keys are the fvar names as strings
- - The values are the offsets from the base fvars_table address in bytes
- For example: [("boolean?", 0)]
- *)
- val make_fvars_tbl : expr' list -> (string * int) list
- (* This signature represents the idea of outputing assembly code as a string
- for a single AST', given the full constants and fvars tables.
- *)
- val generate : (constant * (int * string)) list -> (string * int) list -> expr' -> string
- (* val generate2 : expr' list -> string list *)
- end;;
- (* ------------------------------------------- labels ------------------------------------------*)
- let label_table = ref []
- let env = ref 0
- let tagged_sexpr_table = ref []
- let tagged_name_offset = ref []
- let tableIter = ref []
- let label_for_gen = ref 0
- let rec labels_expr e=
- (function
- |(Var'(body))-> Var'(body)
- |(LambdaSimple'(args,body)) ->LambdaSimple'(args,labels_expr(body))
- |(LambdaOpt'(args,arg2,body)) ->LambdaOpt'(args,arg2,labels_expr(body))
- |(Set'(body1,body2)) -> Set'(labels_expr(body1),labels_expr(body2))
- |(BoxSet'(x,body2)) -> BoxSet'(x, labels_expr(body2))
- |(BoxGet'(x)) -> BoxGet'(x)
- |(Box'(x)) -> Box'(x)
- |(Const'(x)) -> env:= !env +1; Const'(label_maker(x,label_table, env))
- |(If'(test,dit,dif))-> If'(labels_expr(test),labels_expr(dit),labels_expr(dif))
- |(Seq'(args)) -> Seq'(List.map (fun a -> labels_expr(a)) args)
- |(Def'(a,body2)) -> Def'(a,labels_expr(body2))
- |(Or'(args)) -> Or'(List.map (fun a -> labels_expr(a)) args)
- |(Applic'(arg2,args)) ->Applic'(labels_expr(arg2),List.map (fun a -> labels_expr(a)) args)
- |(ApplicTP'(arg2,args)) ->ApplicTP'(labels_expr(arg2),List.map (fun a -> labels_expr(a)) args)
- )e
- and label_maker e = (function
- | (Void, label_table,env) -> Void
- | (Sexpr(Pair(arg1,arg2)), label_table, env) ->
- let arg3 = label_maker_helper(arg1,label_table, env) in
- let arg4 = label_maker_helper(arg2,label_table, env) in
- Sexpr(Pair(arg3,arg4))
- | (Sexpr(TaggedSexpr (str,expr)), label_table, env) -> generate_label(str,label_table, env); Sexpr(TaggedSexpr(label_getter(str,label_table, env),label_maker_helper(expr,label_table, env)))
- | (Sexpr(TagRef (str)), label_table, env) -> generate_label(str,label_table, env); Sexpr(TagRef(label_getter(str,label_table, env)))
- | (Sexpr(x), label_table, env) -> Sexpr(x)
- ) e
- and label_maker_helper e = (function
- | (Pair(arg1,arg2), label_table, env) ->
- let arg3 = label_maker_helper(arg1,label_table, env) in
- let arg4 = label_maker_helper(arg2,label_table, env) in
- Pair(arg3,arg4)
- | (TaggedSexpr (str,expr), label_table, env) -> generate_label (str,label_table, env); TaggedSexpr(label_getter(str,label_table, env),label_maker_helper(expr,label_table, env))
- | (TagRef (str), label_table, env) -> generate_label(str,label_table, env); TagRef(label_getter(str,label_table, env))
- | (x, label_table, env) -> x
- ) e
- and generate_label e = (function
- | (arg,label_table, env) -> if (List.exists (fun (a,b,c) -> (String.equal arg a)) !label_table) then
- ((fun (a,b,c) -> if (!c = !env) then () else (b:= !b+1; c:= !env))(List.find (fun (a,b,c) -> (String.equal arg a)) !label_table))
- else (label_table := (List.append !label_table [(arg, ref 1, ref !env)]))
- )e
- and label_getter e = (function
- | (arg,label_table, env) ->((fun (a,b,c) ->a^(string_of_int !b))(List.find (fun (a,b,c) -> (String.equal arg a)) !label_table))
- )e
- (*---------------------------------------------tag table - second iter --------------------------*)
- and tagged_sexpr_func e=
- (function
- |(Var'(body))-> Var'(body)
- |(LambdaSimple'(args,body)) ->LambdaSimple'(args,tagged_sexpr_func(body))
- |(LambdaOpt'(args,arg2,body)) ->LambdaOpt'(args,arg2,tagged_sexpr_func(body))
- |(Set'(body1,body2)) -> Set'(tagged_sexpr_func(body1),tagged_sexpr_func(body2))
- |(BoxSet'(x,body2)) -> BoxSet'(x,tagged_sexpr_func(body2))
- |(BoxGet'(x)) -> BoxGet'(x)
- |(Box'(x)) -> Box'(x)
- |(Const'(x)) -> Const'(tagged_sexpr_maker(x))
- |(If'(test,dit,dif))-> If'(tagged_sexpr_func(test),tagged_sexpr_func(dit),tagged_sexpr_func(dif))
- |(Seq'(args)) -> Seq'((List.map (fun a -> tagged_sexpr_func(a)) args) )
- |(Def'(a,body2)) -> Def'(tagged_sexpr_func(a),tagged_sexpr_func(body2))
- |(Or'(args)) -> Or'((List.map (fun a -> tagged_sexpr_func(a)) args) )
- |(Applic'(arg2,args)) ->Applic'(tagged_sexpr_func(arg2),(List.map (fun a -> tagged_sexpr_func(a)) args))
- |(ApplicTP'(arg2,args)) ->ApplicTP'(tagged_sexpr_func(arg2),(List.map (fun a -> tagged_sexpr_func(a)) args))
- )e
- and tagged_sexpr_maker e = (function
- | (Void) -> Void
- | (Sexpr(Pair(arg1,arg2))) ->
- let arg3 = tagged_sexpr_helper(arg1) in
- let arg4 = tagged_sexpr_helper(arg2) in
- Sexpr(Pair(arg3,arg4))
- | (Sexpr(TaggedSexpr (str,expr))) -> tagged_sexpr_table := (List.append !tagged_sexpr_table [(str,Sexpr(tagged_sexpr_helper_double(expr)))]); Sexpr(TaggedSexpr(str,tagged_sexpr_helper(expr)))
- | (Sexpr(TagRef (str))) -> Sexpr(TagRef (str))
- | (Sexpr(x)) -> Sexpr(x)
- ) e
- and tagged_sexpr_helper e = (function
- | (Pair(arg1,arg2)) ->
- let arg3 = tagged_sexpr_helper(arg1) in
- let arg4 = tagged_sexpr_helper(arg2) in
- Pair(arg3,arg4)
- | (TaggedSexpr (str,expr)) -> tagged_sexpr_table := (List.append !tagged_sexpr_table [(str,Sexpr(tagged_sexpr_helper_double(expr)))]); TaggedSexpr(str,tagged_sexpr_helper(expr))
- | (TagRef (str)) -> TagRef (str)
- | (x) -> x
- ) e
- and tagged_sexpr_helper_double e = (function
- | (Pair(arg1,arg2)) ->
- let arg3 = tagged_sexpr_helper_double(arg1) in
- let arg4 = tagged_sexpr_helper_double(arg2) in
- Pair(arg3,arg4)
- | (TaggedSexpr (str,expr)) -> tagged_sexpr_helper_double(expr)
- | (TagRef (str)) -> TagRef (str)
- | (x) -> x
- ) e
- (* ------------------------------------------ const table ------------------------------------- *)
- let rec create_const_table e=
- (function
- | (Const'(arg),current_table, offset) ->create_const_table_helper(arg,current_table, offset)
- | (Var'(arg),current_table, offset) -> ()
- | (Box'(arg),current_table, offset) -> ()
- | (BoxGet'(arg),current_table, offset) -> ()
- | (BoxSet'(arg, expr),current_table, offset) -> create_const_table(expr,current_table,offset)
- | (If'(test,dit,dif),current_table, offset) -> create_const_table(test,current_table, offset);create_const_table(dit,current_table, offset);create_const_table(dif,current_table, offset);()
- | (Seq'(args),current_table, offset) ->(List.iter (fun arg -> create_const_table(arg,current_table, offset)) args) ; ()
- | (Set'(arg1,arg2),current_table, offset) -> create_const_table(arg2,current_table, offset);()
- | (Def'(arg1,arg2),current_table, offset) -> create_const_table(arg2,current_table, offset);()
- | (Or'(args),current_table, offset) -> (List.iter (fun arg -> create_const_table(arg,current_table, offset)) args) ; ()
- | (LambdaSimple'(args_list, expr),current_table, offset) -> create_const_table(expr,current_table, offset);()
- | (LambdaOpt'(args_list,arg,expr),current_table, offset) -> create_const_table(expr,current_table, offset);()
- | (Applic'(arg,args),current_table, offset) -> create_const_table(arg,current_table, offset);(List.iter (fun arg2 -> create_const_table(arg2,current_table, offset)) args) ; ()
- | (ApplicTP'(arg,args),current_table, offset) -> create_const_table(arg,current_table, offset);(List.iter (fun arg2 -> create_const_table(arg2,current_table, offset)) args) ; ()
- )e
- and offset_in_table e = (function
- | (table, arg) -> get_offset(List.find (function
- | (_,(Sexpr(x),_)) -> sexpr_eq arg x
- | (_,(Void,_)) -> false
- ) !table)
- )e
- and get_offset e = (function
- |(_,(_,offset)) -> offset
- )e
- and create_const_table_helper e = (function
- | (Void,current_table, offset) -> ()
- | (Sexpr(Bool(arg)),current_table, offset) -> ()
- | (Sexpr(Nil),current_table, offset) -> ()
- | (Sexpr(Char(arg)),current_table, offset) -> if (List.exists ( function
- |(_,(Sexpr(arg2),_))-> sexpr_eq arg2 (Char(arg))
- |(_,(Void,_))-> false
- ) !current_table)
- then ()
- else (current_table := !current_table @ [((Printf.sprintf "MAKE_LITERAL_CHAR(%d)" (Char.code arg)),(Sexpr(Char(arg)),!offset))]);
- offset:=!offset+2
- | (Sexpr(Number(Int(arg))),current_table, offset) -> if (List.exists ( function
- |(_,(Sexpr(arg2),_))-> sexpr_eq arg2 (Number(Int(arg)))
- |(_,(Void,_))-> false
- ) !current_table)
- then ()
- else (current_table := !current_table @[((Printf.sprintf "MAKE_LITERAL_INT(%d)" arg),(Sexpr(Number(Int(arg))),!offset))]; offset:=!offset+9)
- | (Sexpr(Number(Float(arg))),current_table, offset) -> if (List.exists ( function
- |(_,(Sexpr(arg2),_))-> sexpr_eq arg2 (Number(Float(arg)))
- |(_,(Void,_))-> false
- ) !current_table)
- then ()
- else (current_table := !current_table @[((Printf.sprintf "MAKE_LITERAL_FLOAT(%f)" arg),(Sexpr(Number(Float(arg))),!offset))]; offset:=!offset+9)
- | (Sexpr(String(arg)),current_table, offset) -> if (List.exists ( function
- |(_,(Sexpr(arg2),_))-> sexpr_eq arg2 (String(arg))
- |(_,(Void,_))-> false
- ) !current_table)
- then ()
- else (current_table := !current_table @[((Printf.sprintf "MAKE_LITERAL_STRING \"%s\"" arg),(Sexpr(String(arg)),!offset))]; offset:=!offset+9+(String.length arg))
- | (Sexpr(Symbol(arg)),current_table, offset) -> if (List.exists ( function
- |(_,(Sexpr(arg2),_))-> sexpr_eq arg2 (Symbol(arg))
- |(_,(Void,_))-> false
- ) !current_table)
- then ()
- else (create_const_table_helper(Sexpr(String(arg)),current_table, offset);current_table := !current_table @[(Printf.sprintf "MAKE_LITERAL_SYMBOL(const_tbl+"^(string_of_int (offset_in_table (current_table,String(arg))))^")" ,(Sexpr(Symbol(arg)),!offset))]; offset:=!offset+9)
- | (Sexpr(Pair(arg1,arg2)),current_table, offset) -> if (List.exists ( function
- |(_,(Sexpr(arg3),_))-> sexpr_eq arg3 (Pair(arg1,arg2))
- |(_,(Void,_))-> false
- ) !current_table)
- then ()
- else (create_const_table_helper(Sexpr(arg1),current_table, offset);
- create_const_table_helper(Sexpr(arg2),current_table, offset);
- current_table := !current_table @[((Printf.sprintf "MAKE_LITERAL_PAIR(const_tbl+%d, const_tbl+%d)" (offset_in_table(current_table,arg1)) (offset_in_table(current_table,arg2))),(Sexpr(Pair(arg1,arg2)),!offset))]; offset:=!offset+17)
- | (Sexpr(TaggedSexpr (str,expr)),current_table, offset) ->
- let newExp = ((fun(s1,e1)->e1) (List.find (fun (s,e) -> s=str) !tagged_sexpr_table)) in
- create_const_table_helper(newExp,current_table, offset)
- | (Sexpr(TagRef (str)),current_table, offset) ->
- (current_table := !current_table @ [((Printf.sprintf "Tag ref HERE"),(Sexpr(TagRef (str)), find_offset_for_ref(str,current_table)))]);
- ) e
- and find_offset_for_ref e = (function
- | (str,current_table) ->
- let newExp = ((function
- |(s1,Sexpr(e1))->e1
- |(_,Void)->Number(Int 5)
- ) (List.find (fun (s,e) -> s=str) !tagged_sexpr_table)) in
- (if (List.exists (function
- |(s2,(Sexpr(e2),of2)) -> sexpr_eq e2 newExp
- |(s2,(Void,of2)) -> false)
- !tableIter)
- then ((fun (_,(_,offset2))-> offset2)(List.find (function
- |(s2,(Sexpr(e2),of2)) -> sexpr_eq e2 newExp
- |(s2,(Void,of2)) -> false)
- !tableIter))
- else (9999999999999999))
- )e;;
- (* ----------------------------------------- free table--------------------------------------- *)
- let rec create_free_table e= (function
- | (Const'(arg),current_table, offset) -> ()
- | (Var'(VarFree(arg)),current_table, offset) -> add_free(arg,current_table, offset); ()
- | (Var'(arg),current_table, offset) -> ()
- | (Box'(arg),current_table, offset) -> ()
- | (BoxGet'(arg),current_table, offset) -> ()
- | (BoxSet'(arg, expr),current_table, offset) -> create_free_table(expr,current_table,offset)
- | (If'(test,dit,dif),current_table, offset) -> create_free_table(test,current_table, offset);create_free_table(dit,current_table, offset);create_free_table(dif,current_table, offset);()
- | (Seq'(args),current_table, offset) ->(List.iter (fun arg -> create_free_table(arg,current_table, offset)) args) ; ()
- | (Set'(arg1,arg2),current_table, offset) -> create_free_table(arg2,current_table, offset);()
- | (Def'(arg1,arg2),current_table, offset) -> create_free_table(arg1,current_table, offset);create_free_table(arg2,current_table, offset);()
- | (Or'(args),current_table, offset) -> (List.iter (fun arg -> create_free_table(arg,current_table, offset)) args) ; ()
- | (LambdaSimple'(args_list, expr),current_table, offset) -> create_free_table(expr,current_table, offset);()
- | (LambdaOpt'(args_list,arg,expr),current_table, offset) -> create_free_table(expr,current_table, offset);()
- | (Applic'(arg,args),current_table, offset) -> create_free_table(arg,current_table, offset);(List.iter (fun arg2 -> create_free_table(arg2,current_table, offset)) args) ; ()
- | (ApplicTP'(arg,args),current_table, offset) -> create_free_table(arg,current_table, offset);(List.iter (fun arg2 -> create_free_table(arg2,current_table, offset)) args) ; ()
- )e
- and add_free e =(fun (arg, free_table, offset) -> if (List.exists (function
- |(name,_)-> sexpr_eq (String(name)) (String(arg))
- ) !free_table)
- then ()
- else (free_table := !free_table @[(arg,!offset)]; offset:=!offset+1)
- )e;;
- let rec offset_free e = (function
- | (table, arg) -> get_free_offset(List.find (function
- | (str,offset) -> sexpr_eq (String(arg)) (String(str))
- ) !table)
- )e
- and get_free_offset e = (function
- |(_,offset) -> offset
- )e
- and offset_constant e = (function
- | (table, Sexpr(arg)) -> get_constant_offset(List.find (function
- | (Sexpr(x),(_,_)) -> sexpr_eq arg x
- | (Void,(_,_)) -> false
- ) !table)
- | (table, Void) -> 0
- )e
- and get_constant_offset e = (function
- |(_,(offset,_)) -> offset
- )e;;
- let rec generate_helper e = (function
- | (label_counter,depth,outer_params,const_table,free_table,Const'(Sexpr(TaggedSexpr (str,expr)))) -> (Printf.sprintf "mov rax, const_tbl+%d\n" (offset_constant(const_table,Sexpr(expr))))
- | (label_counter,depth,outer_params,const_table,free_table,Const'(arg)) -> (Printf.sprintf "mov rax, const_tbl+%d\n" (offset_constant(const_table,arg)))
- | (label_counter,depth,outer_params,const_table,free_table,Var'(VarParam(arg,minor))) -> (Printf.sprintf "mov rax, qword[rbp+8*(4+%d)]\n" minor)
- | (label_counter,depth,outer_params,const_table,free_table,Var'(VarBound(arg,major,minor))) -> (Printf.sprintf "mov rax, qword[rbp+(8*2)]\n" )^
- (Printf.sprintf "mov rax, qword[rax+(WORD_SIZE*%d)]\n" major)^
- (Printf.sprintf "mov rax, qword[rax+(WORD_SIZE*%d)]\n" minor)
- | (label_counter,depth,outer_params,const_table,free_table,Var'(VarFree(arg))) -> (Printf.sprintf "mov rax, qword[fvar_tbl+WORD_SIZE*%d]\n" (offset_free(free_table,arg)))
- | (label_counter,depth,outer_params,const_table,free_table,Box'(arg)) -> (generate_helper(label_counter,depth,outer_params,const_table,free_table,Var'(arg)))^(Printf.sprintf "MALLOC r8, WORD_SIZE \nmov [r8], rax \nmov rax, r8\n")
- | (label_counter,depth,outer_params,const_table,free_table,BoxGet'(arg)) -> (generate_helper(label_counter,depth,outer_params,const_table,free_table,Var'(arg)))^(Printf.sprintf "mov rax, qword[rax]\n")
- | (label_counter,depth,outer_params,const_table,free_table,BoxSet'(arg, expr)) -> (generate_helper(label_counter,depth,outer_params,const_table,free_table,expr))^(Printf.sprintf "push rax\n")^
- (generate_helper(label_counter,depth,outer_params,const_table,free_table,Var'(arg)))^(Printf.sprintf "pop qword[rax]\n")^(Printf.sprintf "mov rax, SOB_VOID_ADDRESS\n")
- | (label_counter,depth,outer_params,const_table,free_table,If'(test,dit,dif)) -> label_counter := !label_counter + 1; let anotherLabel = !label_counter in
- (generate_helper(label_counter,depth,outer_params,const_table,free_table,test))^(Printf.sprintf "cmp rax, SOB_FALSE_ADDRESS\n")^ (Printf.sprintf "je Lelse%d\n" anotherLabel)^
- (generate_helper(label_counter,depth,outer_params,const_table,free_table,dit))^(Printf.sprintf "jmp Lexit%d\n" anotherLabel)^ (Printf.sprintf "Lelse%d:\n" anotherLabel)^
- (generate_helper(label_counter,depth,outer_params,const_table,free_table,dif))^(Printf.sprintf "Lexit%d:\n" anotherLabel)
- | (label_counter,depth,outer_params,const_table,free_table,Seq'(args)) ->(List.fold_left (fun arg1 arg2 -> arg1^(generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2))) "" args)
- | (label_counter,depth,outer_params,const_table,free_table,Set'(Var'(VarParam(arg1,minor)),arg2)) -> generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2)^ (Printf.sprintf "mov qword[rbp+WORD_SIZE*(4+%d)],rax\n" minor)^(Printf.sprintf "mov rax, SOB_VOID_ADDRESS\n")
- | (label_counter,depth,outer_params,const_table,free_table,Set'(Var'(VarBound(arg1,major,minor)),arg2)) -> generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2)^
- (Printf.sprintf "mov rbx, qword[rbp+WORD_SIZE*2]\n")^
- (Printf.sprintf "mov rbx, qword[rbx+WORD_SIZE*%d]\n" major)^
- (Printf.sprintf "mov qword[rbx+WORD_SIZE*%d], rax\n" minor)^
- (Printf.sprintf "mov rax, SOB_VOID_ADDRESS\n")
- | (label_counter,depth,outer_params,const_table,free_table,Set'(Var'(VarFree(arg1)),arg2)) -> generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2)^ (Printf.sprintf "mov qword[fvar_tbl+WORD_SIZE*%d],rax\n" (offset_free(free_table,arg1)))^(Printf.sprintf "mov rax, SOB_VOID_ADDRESS\n")
- | (label_counter,depth,outer_params,const_table,free_table,Def'(Var'(VarFree(arg1)),arg2)) -> let a = generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2)in
- let b = (Printf.sprintf "mov qword[fvar_tbl+WORD_SIZE*%d],rax\n" (offset_free(free_table,arg1)))in
- let c =(Printf.sprintf "mov rax, SOB_VOID_ADDRESS\n")in
- a^b^c
- | (label_counter,depth,outer_params,const_table,free_table,Or'(args)) -> label_counter := !label_counter + 1; let anotherLabel = !label_counter in let c = ref 0 in
- (List.fold_left (fun arg1 arg2 ->c := !c+1 ; if (!c = List.length args)
- then (arg1^generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2)^(Printf.sprintf "Lexit%d:\n" anotherLabel))
- else (arg1^generate_helper(label_counter,depth,outer_params,const_table,free_table,arg2)^
- (Printf.sprintf "cmp rax, SOB_FALSE_ADDRESS\n")^(Printf.sprintf "jne Lexit%d\n" anotherLabel))) "" args)
- | (label_counter,depth,outer_params,const_table,free_table,LambdaSimple'(args_list, expr)) ->label_counter := !label_counter + 1; lambda_simple_maker(label_counter,depth,outer_params,const_table,free_table,LambdaSimple'(args_list, expr))
- | (label_counter,depth,outer_params,const_table,free_table,LambdaOpt'(args_list,arg,expr)) -> label_counter := !label_counter + 1; lambda_opt_maker(label_counter,depth,outer_params,const_table,free_table,LambdaOpt'(args_list, arg, expr))
- | (label_counter,depth,outer_params,const_table,free_table,Applic'(arg,args)) ->label_counter := !label_counter + 1;
- "mov r8, SOB_NIL_ADDRESS\n"^
- (Printf.sprintf "push r8\n")^ (*push magic*)
- (List.fold_right (fun cur acc ->acc ^ generate_helper(label_counter,depth,outer_params,const_table,free_table,cur) ^ (Printf.sprintf "push rax \n") ) args "")^
- (Printf.sprintf "push %d\n" (List.length args))^
- generate_helper(label_counter,depth,outer_params,const_table,free_table,arg)^
- "CLOSURE_ENV r8, rax\n"^
- "push r8\n"^
- "CLOSURE_CODE r9, rax\n"^
- "call r9\n"^
- "add rsp, WORD_SIZE\n"^
- "pop rbx\n"^
- "inc rbx\n"^ (*increase for magic? *)
- "shl rbx, 3\n"^
- "add rsp, rbx\n"
- | (label_counter,depth,outer_params,const_table,free_table,ApplicTP'(arg,args)) -> label_counter := !label_counter + 1;
- "mov r8, SOB_NIL_ADDRESS\n"^
- (Printf.sprintf "push r8\n")^ (*push magic*)
- (List.fold_right (fun cur acc ->acc ^ generate_helper(label_counter,depth,outer_params,const_table,free_table,cur) ^ (Printf.sprintf "push rax \n") ) args "")^
- (Printf.sprintf "push %d\n" (List.length args))^
- generate_helper(label_counter,depth,outer_params,const_table,free_table,arg)^
- "CLOSURE_ENV r8, rax\n"^
- "push r8\n"^
- "push qword[rbp + 8]\n"^
- "mov r13, [rbp]\n"^ (*maybe push?*)
- (Printf.sprintf "SHIFT_FRAME %d\n" ((List.length args)+5))^
- "mov rbp, r13\n"^
- "CLOSURE_CODE r9, rax\n"^
- "jmp r9\n"
- (* "leave\n"^
- "ret\n" *)
- |_ -> raise X_no_match
- ) e
- and lambda_simple_maker e =
- let env=ref "" in
- let newEnv = ref "" in
- (function
- | (label_counter,depth,outer_params,const_table,free_table,LambdaSimple'(args_list, expr)) ->
- let anotherLabel = !label_counter in
- for i=depth downto 1 do
- (
- env := !env ^ (Printf.sprintf "mov r8, [rbx+%d*8] \nmov [rax+%d*8], r8 \n" (i-1) i)
- )done;
- for i=outer_params downto 1 do
- (
- newEnv := !newEnv ^ (Printf.sprintf "mov r9, [rbp+%d*8] \nmov [rax+%d*8], r9 \n"
- (4+(i-1)) (i-1))
- )done;
- (Printf.sprintf "MALLOC rax, %d\n" (8*(depth+1)))^
- (Printf.sprintf "mov rbx, qword[rbp+16] ; lex env\n") ^ ";start of env\n" ^
- !env ^
- (if outer_params=0 || depth=0 then (Printf.sprintf "mov rax, SOB_NIL_ADDRESS\nmov r8, rax ;enter to the then in lambda simple\n")
- else((Printf.sprintf "mov r8, rax \nMALLOC rax, %d ;malloc for array of outer params\nmov [r8], rax ;move the empty array to extEnv[0]\n"
- (8*outer_params)) ^
- !newEnv))^
- (Printf.sprintf "MAKE_CLOSURE(rax, r8, Lcode%d)\n jmp Lcont%d\nLcode%d:\nenter 0,0\n" anotherLabel anotherLabel anotherLabel)^
- generate_helper(label_counter,depth+1,(List.length args_list),const_table,free_table,expr) ^
- (Printf.sprintf "leave\nret\nLcont%d:\n" anotherLabel)
- | _ -> raise X_no_match
- )e
- and lambda_opt_maker e =
- let env=ref "" in
- let newEnv = ref "" in
- (function
- | (label_counter,depth,outer_params,const_table,free_table,LambdaOpt'(args_list,arg,expr)) ->
- let anotherLabel = !label_counter in
- for i=depth downto 1 do
- (
- env := !env ^ (Printf.sprintf "mov r8, [rbx+%d*WORD_SIZE] \nmov [rax+%d*WORD_SIZE], r8 \n" (i-1) i)
- )done;
- for i=outer_params downto 1 do
- (
- newEnv := !newEnv ^ (Printf.sprintf "mov r9, [rbp+%d*WORD_SIZE] \nmov [rax+%d*WORD_SIZE], r9 \n"
- (4+(i-1)) (i-1))
- )done;
- (Printf.sprintf "MALLOC rax, %d\n" (8*(depth+1)))^
- (Printf.sprintf "mov rbx, qword[rbp+16] ; lex env\n") ^ ";start of env\n" ^
- !env ^
- (if outer_params=0 || depth=0 then (Printf.sprintf "mov qword[rax], SOB_NIL_ADDRESS\nmov r8, rax ;enter to the then in lambda simple\n")
- else((Printf.sprintf "mov r8, rax \nMALLOC rax, %d ;malloc for array of outer params\nmov [r8], rax ;move the empty array to extEnv[0]\n"
- (8*outer_params)) ^
- !newEnv))^
- (Printf.sprintf "MAKE_CLOSURE(rax, r8, Lcode%d)\n jmp Lcont%d\nLcode%d:\nenter 0,0\n" anotherLabel anotherLabel anotherLabel)^
- lambda_opt_maker_helper((List.length args_list)+1, label_counter)^
- generate_helper(label_counter,depth+1,(List.length args_list)+1,const_table,free_table,expr) ^
- (Printf.sprintf "leave\nret\nLcont%d:\n" anotherLabel)
- | _ -> raise X_no_match
- )e
- and lambda_opt_maker_helper e = (function
- | (args_num, counter) -> counter := !counter + 1; (*line 403 is redundent*)
- (Printf.sprintf
- "mov r8, [rbp+24] ; num of args in applic
- mov rcx, r8
- inc rcx; plus one for magic
- sub rcx, %d ; substitute the num of args in opt
- cmp rcx, 0 ; num of args in opt = minimum number of args
- jle end_of_cont%d
- add r8, 4
- opt_loop%d:
- dec r8
- mov r9, [rbp +WORD_SIZE*(r8+1)]
- mov r10, [rbp+ WORD_SIZE*r8]
- MAKE_PAIR (rax, r10, r9)
- mov [rbp + WORD_SIZE*r8], rax
- loop opt_loop%d
- end_of_cont%d:\n" args_num !counter !counter !counter !counter)
- )e;;
- module Code_Gen : CODE_GEN = struct
- let make_consts_tbl asts =
- tagged_sexpr_table := [];
- env := 0;
- label_table := [];
- let refForTable1 = ref 6 in
- let refForTable2 = ref 6 in
- let table = ref [("MAKE_VOID",(Void,0));("MAKE_NIL",(Sexpr(Nil),1));("MAKE_BOOL(0)",(Sexpr(Bool(false)),2));("MAKE_BOOL(1)",(Sexpr(Bool(true)),4))] in
- tableIter := [("MAKE_VOID",(Void,0));("MAKE_NIL",(Sexpr(Nil),1));("MAKE_BOOL(0)",(Sexpr(Bool(false)),2));("MAKE_BOOL(1)",(Sexpr(Bool(true)),4))];
- List.iter (
- fun(x)->create_const_table (x, tableIter, refForTable1);
- create_const_table (x, table, refForTable2))
- (List.map (fun e -> tagged_sexpr_func(labels_expr e)) asts);
- (List.filter (function
- | (Sexpr(TagRef(a)),(b,c)) -> false
- | (a,(b,c)) -> true
- )
- (List.map (fun (a,(b,c))->(b,(c,a))) !table));;
- let make_fvars_tbl asts =
- let fvar_ref = ref 43 in
- let free_table = ref [("append", 0);("apply",1);("<",2); ("=",3);(">",4);("+",5);
- ("/",6);("*",7);("-",8);("boolean?",9);("car",10);("cdr",11);
- ("char->integer",12);("char?",13);("cons",14);("eq?",15);("equal?",16);("fold-left",17);
- ("fold-right",18);("integer?",19);("integer->char",20);("length",21);("list",22);
- ("list?",23);("make-string",24);("map",25);("not",26);("null?",27);("number?",28);
- ("pair?",29);("procedure?",30);("float?",31);("set-car!",32);("set-cdr!",33);
- ("string->list",34);("string-length",35);("string-ref",36);("string-set!",37);
- ("string?",38);("symbol?",39);("symbol->string",40);("zero?",41);("cons*",42);
- (* you can add yours here *)] in
- List.iter (
- fun(x)->create_free_table (x, free_table, fvar_ref)
- ) asts;
- !free_table;;
- let generate consts fvars e = env := 0; generate_helper (label_for_gen, 0, 0, ref consts, ref fvars, (labels_expr e));;
- (* let generate2 e1 = List.map (fun e -> generate (make_consts_tbl e1) (make_fvars_tbl e1) ) e1;; *)
- end;;
- (* self comment - string is in asci and not string *)
- (* Code_Gen.generate (Semantics.run_semantics (Tag_Parser.tag_parse_expression (Reader.read_sexpr "1")));; *)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement