Update hw5 to a newer version.

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2025-01-24 21:10:31 -08:00
parent b24a264f7e
commit 9224001a22
262 changed files with 2575 additions and 1442 deletions

2
hw5/.ocamlformat Normal file
View file

@ -0,0 +1,2 @@
profile = janestreet
version = 0.26.1

1
hw5/.ocamlinit Normal file
View file

@ -0,0 +1 @@
#use_output "dune top";;

View file

@ -1,26 +1,27 @@
INCLUDES= util,x86,grading,ll
LIBS = unix,str
SUBMIT := frontend.ml typechecker.ml team.txt
SUBMIT := $(shell cat submit_zip_contents.txt)
HWNAME := hw5
TIMESTAMP := $(shell /bin/date "+%Y-%m-%d-%H:%M:%S")
ZIPNAME := $(HWNAME)-submit-$(TIMESTAMP).zip
HWNAME := hw05
ZIPNAME := $(HWNAME)-submit.zip
.PHONY: all oatc test clean zip
all: oatc
all: main.native
oatc:
dune build
@cp bin/main.exe oatc
.PHONY: test
test: main.native
./main.native --test
test: oatc
./oatc --test
.PHONY: main.native
main.native:
ocamlbuild -pkg num -Is $(INCLUDES) -libs $(LIBS) main.native -use-menhir -yaccflag --explain
utop:
dune utop
zip: $(SUBMIT)
zip '$(ZIPNAME)' $(SUBMIT)
.PHONY: clean
clean:
ocamlbuild -clean
rm -rf output a.out
dune clean
rm -rf oatc ocamlbin bin/main.exe
#

View file

@ -1,69 +0,0 @@
Using main.native for testing:
* To run the automated test harness do:
- on OS X: ./main.native --test
- on Linux: ./main.native -linux --test
* To compile ll files using the 341 backend:
./main.native path/to/foo.ll
- creates output/foo.s backend assembly code
- creates output/foo.o assembled object file
- creates a.out linked executable
NOTE: by default the .s and .o files are created in
a directory called output, and the filenames are
chosen so that multiple runs of the compiler will
not overwrite previous outputs. foo.ll will be
compiled first to foo.s then foo_1.s, foo_2.s, etc.
* To compile ll files using the clang backend:
./main.native --clang path/to/foo.ll
* Useful flags:
--print-ll
echoes the ll program to the terminal
--print-x86
echoes the resulting .s file to the terminal
--simulate-x86
runs the resulting .s file through the reference
x86 simulator and outputs the result to the console
--execute-x86
runs the resulting a.out file natively
(applies to either the 341 backend or clang-compiled code)
-v
generates verbose output, showing which commands are used
for linking, etc.
-op <dirname>
change the output path [DEFAULT=output]
-o
change the generated executable's name [DEFAULT=a.out]
-S
stop after generating .s files
-c
stop after generating .o files
-h or --help
display the list of options
* Example uses:
Run the test case /programs/factrect.ll using the 341 backend:
./main.native --execute-x86 programs/factrect.ll
--------------------------------------------------------------- Executing: a.out
* a.out returned 120
Run the test

73
hw5/README.md Normal file
View file

@ -0,0 +1,73 @@
# HW5: Oat v.2 -- Typechecking Structs, Function Pointers, and Subtyping
Quick Start:
1. clone this repository using `git clone`
2. open the folder in VSCode
3. start an OCaml sandbox terminal
4. run `make test` from the command line
5. open `bin/frontend.ml`
See the general toolchain and project instructions on the course web site. The
course web pages have a link to the html version of the homework instructions.
Using ``oatc``
--------------
``oatc`` acts like the clang compiler. Given several .oat, .ll, .c, and .o
files, it will compile the .oat and .ll files to .s files (using the cs131
frontend and backend) and then combine the results with the .c and .o files to
produce an executable named a.out. You can also compile the .ll files using
clang instead of the cs131 backend, which can be useful for testing
purposes.
* To run the automated test harness do:
./oatc --test
* To compile oat files using the 131 backend:
./oatc path/to/foo.oat
- creates output/foo.ll frontend ll code
- creates output/foo.s backend assembly code
- creates output/foo.o assembled object file
- creates a.out linked executable
NOTE: by default the .s and .o files are created in
a directory called output, and the filenames are
chosen so that multiple runs of the compiler will
not overwrite previous outputs. foo.ll will be
compiled first to foo.s then foo_1.s, foo_2.s, etc.
* To compile oat files using the clang backend:
./oatc --clang path/to/foo.oat
* Useful flags:
| Flag | Description |
|-------------------|---------------------------------------------------------------------------------------------------|
| --print-oat | pretty prints the Oat abstract syntax to the terminal |
| --print-ll | echoes the ll program to the terminal |
| --print-x86 | echoes the resulting .s file to the terminal |
| --interpret-ll | runs the ll file through the reference interpreter and outputs the results to the console |
| --execute-x86 | runs the resulting a.out file natively (applies to either the 131 backend or clang-compiled code) |
| --clang | compiles to assembly using clang, not the 131 backend |
| -v | generates verbose output, showing which commands are used for linking, etc. |
| -op ``<dirname>`` | change the output path [DEFAULT=output] |
| -o | change the generated executable's name [DEFAULT=a.out] |
| -S | stop after generating .s files |
| -c | stop after generating .o files |
| -h or --help | display the list of options |
* Example uses:
Run the test case hw4programs/fact.oat using the 131 backend:
./oatc --execute-x86 hw4programs/fact.oat bin/runtime.c
120--------------------------------------------------------------- Executing: a.out
* a.out returned 0

View file

@ -1,3 +1,4 @@
module Range = Util.Range
type 'a node = { elt : 'a; loc : Range.t }
@ -52,7 +53,8 @@ type exp =
| CStr of string
| Id of id
| CArr of ty * exp node list
| NewArr of ty * exp node * id * exp node
| NewArr of ty * exp node
| NewArrInit of ty * exp node * id * exp node
| Index of exp node * exp node
| Length of exp node
| CStruct of id * (id * exp node) list

View file

@ -112,10 +112,13 @@ and print_exp_aux level fmt e =
| Id id -> print_id_aux fmt id
| Index (e,i) -> print_exp_aux this_level fmt e; pps "["; print_exp_aux 0 fmt i; pps "]"
| Call (e, es) -> print_exp_aux this_level fmt e; print_exps_aux "(" ")" fmt es
| NewArr (ty, e1, u, e2) ->
| NewArr(ty, e1) ->
pps "new"; print_ty_aux fmt ty;
pps "["; print_exp_aux this_level fmt e1; pps "]"
| NewArrInit (ty, e1, u, e2) ->
pps "new"; print_ty_aux fmt ty;
pps "["; print_exp_aux this_level fmt e1;
pps "{"; pps u; pps "->"; print_exp_aux this_level fmt e2
pps "] {"; pps u; pps "->"; print_exp_aux this_level fmt e2; pps "}"
| Bop (o,l,r) ->
pp_open_box fmt 0;
print_exp_aux this_level fmt l;
@ -322,6 +325,8 @@ let string_of_exp (e:exp node) : string = string_of (print_exp_aux 0) e
let print_ty (t:ty) : unit = print print_ty_aux t
let string_of_ty (t:ty) : string = string_of print_ty_aux t
let string_of_ret_ty (r:ret_ty) : string = string_of print_ret_ty_aux r
(* AST to ML *)
let sp = Printf.sprintf
@ -406,7 +411,9 @@ let rec ml_string_of_exp_aux (e: exp) : string =
| Call (e, exps) -> sp "Call (%s, %s)"
(ml_string_of_exp e)
(ml_string_of_list ml_string_of_exp exps)
| NewArr (t,e1,u,e2) -> sp "NewArr (%s,%s,%s,%s)"
| NewArr (t,e1) -> sp "NewArr (%s,%s)"
(ml_string_of_ty t) (ml_string_of_exp e1)
| NewArrInit (t,e1,u,e2) -> sp "NewArrInit (%s,%s,%s,%s)"
(ml_string_of_ty t) (ml_string_of_exp e1) (ml_string_of_id u) (ml_string_of_exp e2)
| Proj(exp, id) -> sp "Proj (%s,%s)" (ml_string_of_exp exp) (ml_string_of_id id)
| Bop (b, e1, e2) -> sp "Bop (%s,%s,%s)"

View file

@ -3,6 +3,8 @@
open Ll
open X86
module Platform = Util.Platform
(* Overview ----------------------------------------------------------------- *)
(* We suggest that you spend some time understinging this entire file and

View file

@ -1,4 +1,8 @@
open Printf
module Platform = Util.Platform
module Range = Util.Range
open Platform
(* configuration flags ------------------------------------------------------ *)
@ -142,7 +146,7 @@ let process_files files =
if (List.length files) > 0 then begin
List.iter process_file files;
( if !assemble && !link then
Platform.link (List.rev !link_files@["runtime.c"]) !executable_filename );
Platform.link (List.rev !link_files) !executable_filename );
( if !assemble && !link && !execute_x86 then
let ret = run_executable "" !executable_filename in
print_banner @@ Printf.sprintf "Executing: %s" !executable_filename;

29
hw5/bin/dune Normal file
View file

@ -0,0 +1,29 @@
(library
(name oat)
(modules driver backend frontend lexer parser ast astlib typechecker tctxt)
(libraries str num util x86 ll))
(ocamllex lexer)
(menhir (modules parser))
(env
(dev
(flags
(:standard -g -w "+a-4-7-9-26-27-29-30-32..42-44-45-48-50-60-66..70")
)))
(executable
(public_name main)
(name main)
(modules main)
(promote (until-clean))
(libraries
; OCaml standard libraries
; project libraries
str
num
util
x86
ll
studenttests
gradedtests))

View file

@ -99,10 +99,10 @@ module TypeCtxt = struct
| h :: t -> if h.fieldName = f then Some i else index_of f t (i + 1)
(* Return the index of a field in the struct. *)
let index_of_field_opt st f (c : t) =
let index_of_field_opt (st:Ast.id) (f:Ast.id) (c : t) : (int option) =
index_of f (List.assoc st c) 0
let index_of_field st f c =
let index_of_field (st:Ast.id) (f:Ast.id) (c:t) : int =
match index_of_field_opt st f c with
| None -> failwith "index_of_field: Not found"
| Some x -> x
@ -112,7 +112,7 @@ module TypeCtxt = struct
let fields = lookup st c in
match index_of f fields 0 with
| None -> failwith "no such field"
| Some x -> List.(nth fields x).ftyp, Int64.of_int x
| Some x -> List.(nth fields x).ftyp, Int64.of_int x
end
(* compiling OAT types ------------------------------------------------------ *)
@ -166,7 +166,7 @@ let gensym : string -> string =
let c = ref 0 in
fun (s:string) -> incr c; Printf.sprintf "_%s%d" s (!c)
(* Amount of space an Oat type takes when stored in the satck, in bytes.
(* Amount of space an Oat type takes when stored in the stack, in bytes.
Note that since structured values are manipulated by reference, all
Oat values take 8 bytes on the stack.
*)
@ -175,7 +175,7 @@ let size_oat_ty (t : Ast.ty) = 8L
(* Generate code to allocate an array of source type TRef (RArray t) of the
(* Generate code to allocate a zero-initialized array of source type TRef (RArray t) of the
given size. Note "size" is an operand whose value can be computed at
runtime *)
let oat_alloc_array ct (t:Ast.ty) (size:Ll.operand) : Ll.ty * operand * stream =
@ -195,7 +195,7 @@ let oat_alloc_array ct (t:Ast.ty) (size:Ll.operand) : Ll.ty * operand * stream =
- make sure to calculate the correct amount of space to allocate!
*)
let oat_alloc_struct ct (id:Ast.id) : Ll.ty * operand * stream =
let oat_alloc_struct (ct:TypeCtxt.t) (id:Ast.id) : Ll.ty * operand * stream =
failwith "TODO: oat_alloc_struct"
@ -243,6 +243,17 @@ let rec cmp_exp (tc : TypeCtxt.t) (c:Ctxt.t) (exp:Ast.exp node) : Ll.ty * Ll.ope
>:: G(gid, (str_typ, GString s))
>:: I(uid, Gep(Ptr str_typ, Gid gid, [Const 0L; Const 0L;]))
| Ast.Bop (Ast.Eq as bop, e1, e2)
| Ast.Bop (Ast.Neq as bop, e1, e2) ->
(* Polymorphic equality operations *)
(* Allow any type for the first operand, and cast
the second operand to the type of the first. *)
let _, _, ret_ty = typ_of_binop bop in
let ll_t, op1, code1 = cmp_exp tc c e1 in
let op2, code2 = cmp_exp_as tc c e2 ll_t in
let ans_id = gensym "bop" in
cmp_ty tc ret_ty, Id ans_id, code1 >@ code2 >:: I(ans_id, cmp_binop ll_t bop op1 op2)
| Ast.Bop (bop, e1, e2) ->
let t, _, ret_ty = typ_of_binop bop in
let ll_t = cmp_ty tc t in
@ -271,7 +282,7 @@ let rec cmp_exp (tc : TypeCtxt.t) (c:Ctxt.t) (exp:Ast.exp node) : Ll.ty * Ll.ope
| _ -> failwith "broken invariant: identifier not a pointer"
end
(* ARRAY TASK: complete this case to compilet the length(e) expression.
(* ARRAY TASK: complete this case to compile the length(e) expression.
The emitted code should yield the integer stored as part
of the array struct representation.
*)
@ -295,12 +306,17 @@ let rec cmp_exp (tc : TypeCtxt.t) (c:Ctxt.t) (exp:Ast.exp node) : Ll.ty * Ll.ope
let ind = gensym "ind" in
s >@ elt_code >@ lift
[ ind, Gep(arr_ty, arr_op, [Const 0L; Const 1L; i64_op_of_int i ])
; "", Store(ll_elt_ty, elt_op, Id ind) ]
; gensym "store", Store(ll_elt_ty, elt_op, Id ind) ]
in
let ind_code = List.(fold_left add_elt [] @@ mapi (fun i e -> i, e) cs) in
arr_ty, arr_op, alloc_code >@ ind_code
(* ARRAY TASK: Modify the compilation of the NewArr construct to implement the
| Ast.NewArr (elt_ty, e) ->
let _, size_op, size_code = cmp_exp tc c e in
let arr_ty, arr_op, alloc_code = oat_alloc_array tc elt_ty size_op in
arr_ty, arr_op, size_code >@ alloc_code
(* ARRAY TASK: Modify the compilation of the NewArrInit construct to implement the
initializer:
- the initializer is a loop that uses id as the index
- each iteration of the loop the code evaluates e2 and assigns it
@ -310,7 +326,7 @@ let rec cmp_exp (tc : TypeCtxt.t) (c:Ctxt.t) (exp:Ast.exp node) : Ll.ty * Ll.ope
you could write the loop using abstract syntax and then call cmp_stmt to
compile that into LL code...
*)
| Ast.NewArr (elt_ty, e1, id, e2) ->
| Ast.NewArrInit (elt_ty, e1, id, e2) ->
let _, size_op, size_code = cmp_exp tc c e1 in
let arr_ty, arr_op, alloc_code = oat_alloc_array tc elt_ty size_op in
arr_ty, arr_op, size_code >@ alloc_code
@ -333,7 +349,10 @@ let rec cmp_exp (tc : TypeCtxt.t) (c:Ctxt.t) (exp:Ast.exp node) : Ll.ty * Ll.ope
and cmp_exp_lhs (tc : TypeCtxt.t) (c:Ctxt.t) (e:exp node) : Ll.ty * Ll.operand * stream =
match e.elt with
| Ast.Id x ->
let t, op = Ctxt.lookup x c in
let pt, op = Ctxt.lookup x c in
let t = match pt with
| Ptr t -> t
| _ -> failwith "Unexpected variable type" in
t, op, []
(* STRUCT TASK: Complete this code that emits LL code to compute the
@ -359,7 +378,7 @@ and cmp_exp_lhs (tc : TypeCtxt.t) (c:Ctxt.t) (e:exp node) : Ll.ty * Ll.operand *
let ans_ty = match arr_ty with
| Ptr (Struct [_; Array (_,t)]) -> t
| _ -> failwith "Index: indexed into non pointer" in
let ptr_id, tmp_id = gensym "index_ptr", gensym "tmp" in
let ptr_id, tmp_id, call_id = gensym "index_ptr", gensym "tmp", gensym "call" in
ans_ty, (Id ptr_id),
arr_code >@ ind_code >@ lift
[ptr_id, Gep(arr_ty, arr_op, [i64_op_of_int 0; i64_op_of_int 1; ind_op]) ]
@ -405,17 +424,17 @@ and cmp_stmt (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmt:Ast.stmt node) : Ctxt
let c' = Ctxt.add c id (Ptr ll_ty, Id res_id) in
c', init_code
>:: E(res_id, Alloca ll_ty)
>:: I("", Store (ll_ty, init_op, Id res_id))
>:: I(gensym "store", Store (ll_ty, init_op, Id res_id))
| Ast.Assn (path ,e) ->
let _, pop, path_code = cmp_exp_lhs tc c path in
let ll_ty, eop, exp_code = cmp_exp tc c e in
c, path_code >@ exp_code >:: I("", (Store (ll_ty, eop, pop)))
let ll_ty, pop, path_code = cmp_exp_lhs tc c path in
let eop, exp_code = cmp_exp_as tc c e ll_ty in
c, path_code >@ exp_code >:: I(gensym "store", (Store (ll_ty, eop, pop)))
| Ast.If (guard, st1, st2) ->
let guard_ty, guard_op, guard_code = cmp_exp tc c guard in
let then_code = cmp_block tc c rt st1 in
let else_code = cmp_block tc c rt st2 in
let _, then_code = cmp_block tc c rt st1 in
let _, else_code = cmp_block tc c rt st2 in
let lt, le, lm = gensym "then", gensym "else", gensym "merge" in
c, guard_code
>:: T(Cbr (guard_op, lt, le))
@ -428,7 +447,7 @@ and cmp_stmt (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmt:Ast.stmt node) : Ctxt
- check whether the value computed by exp is null, if so jump to
the 'null' block, otherwise take the 'notnull' block
- the identifier id is in scope in the 'nutnull' block and so
- the identifier id is in scope in the 'notnull' block and so
needs to be allocated (and added to the context)
- as in the if-the-else construct, you should jump to the common
@ -440,7 +459,7 @@ and cmp_stmt (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmt:Ast.stmt node) : Ctxt
| Ast.While (guard, body) ->
let guard_ty, guard_op, guard_code = cmp_exp tc c guard in
let lcond, lbody, lpost = gensym "cond", gensym "body", gensym "post" in
let body_code = cmp_block tc c rt body in
let _, body_code = cmp_block tc c rt body in
c, []
>:: T (Br lcond)
>:: L lcond >@ guard_code >:: T (Cbr (guard_op, lbody, lpost))
@ -448,12 +467,19 @@ and cmp_stmt (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmt:Ast.stmt node) : Ctxt
>:: L lpost
| Ast.For (inits, guard, after, body) ->
let guard = match guard with Some e -> e | None -> no_loc (CBool true) in
let after = match after with Some s -> [s] | None -> [] in
let body = body @ after in
let ds = List.map (fun d -> no_loc (Decl d)) inits in
let stream = cmp_block tc c rt (ds @ [no_loc @@ Ast.While (guard, body)]) in
c, stream
let ci, init = cmp_block tc c rt ds in
let guard = match guard with Some e -> e | None -> no_loc (CBool true) in
let guard_ty, guard_op, guard_code = cmp_exp tc ci guard in
let after = match after with Some s -> [s] | None -> [] in
let lcond, lbody, lpost = gensym "cond", gensym "body", gensym "post" in
let _,body_code = cmp_block tc ci rt body in
let _,after_code = cmp_block tc ci rt after in
c, init
>:: T (Br lcond)
>:: L lcond >@ guard_code >:: T (Cbr (guard_op, lbody, lpost))
>:: L lbody >@ body_code >@ after_code >:: T (Br lcond)
>:: L lpost
| Ast.Ret None ->
c, [T (Ret(Void, None))]
@ -467,8 +493,8 @@ and cmp_stmt (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmt:Ast.stmt node) : Ctxt
c, code
(* Compile a series of statements *)
and cmp_block (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmts:Ast.block) : stream =
snd @@ List.fold_left (fun (c, code) s ->
and cmp_block (tc : TypeCtxt.t) (c:Ctxt.t) (rt:Ll.ty) (stmts:Ast.block) : Ctxt.t * stream =
List.fold_left (fun (c, code) s ->
let c, stmt_code = cmp_stmt tc c rt s in
c, code >@ stmt_code
) (c,[]) stmts
@ -514,8 +540,8 @@ let cmp_global_ctxt (tc : TypeCtxt.t) (c:Ctxt.t) (p:Ast.prog) : Ctxt.t =
| CNull r -> cmp_ty tc (TNullRef r)
| CBool b -> I1
| CInt i -> I64
| CStr s -> Ptr (str_arr_ty s)
| CArr (u, cs) -> Ptr (Struct [I64; Array(List.length cs, cmp_ty tc u)])
| CStr s -> Ptr I8
| CArr (u, cs) -> Ptr (Struct [I64; Array(0, cmp_ty tc u)])
| x -> failwith ( "bad global initializer: " ^ (Astlib.string_of_exp (no_loc x)))
in
List.fold_left (fun c -> function
@ -537,13 +563,13 @@ let cmp_fdecl (tc : TypeCtxt.t) (c:Ctxt.t) (f:Ast.fdecl node) : Ll.fdecl * (Ll.g
let c = Ctxt.add c s_id (Ptr ll_ty, Ll.Id alloca_id)in
c, []
>:: E(alloca_id, Alloca ll_ty)
>:: I("", Store(ll_ty, Id ll_id, Id alloca_id))
>:: I(gensym "store", Store(ll_ty, Id ll_id, Id alloca_id))
>@ code,
(ll_ty, ll_id)::args
in
let c, args_code, args = List.fold_right add_arg args (c,[],[]) in
let ll_rty = cmp_ret_ty tc frtyp in
let block_code = cmp_block tc c ll_rty body in
let _, block_code = cmp_block tc c ll_rty body in
let argtys, f_param = List.split args in
let f_ty = (argtys, ll_rty) in
let return_code =
@ -551,8 +577,7 @@ let cmp_fdecl (tc : TypeCtxt.t) (c:Ctxt.t) (f:Ast.fdecl node) : Ll.fdecl * (Ll.g
match frtyp with
| RetVoid -> None
| RetVal TBool | RetVal TInt -> Some (Const 0L)
| RetVal (TRef _) -> Some Null
| RetVal (TNullRef _) -> Some Null
| RetVal (TRef _ | TNullRef _) -> Some Null
in
[T (Ret (ll_rty, return_val))]
in
@ -574,7 +599,8 @@ let rec cmp_gexp c (tc : TypeCtxt.t) (e:Ast.exp node) : Ll.gdecl * (Ll.gid * Ll.
| CStr s ->
let gid = gensym "str" in
let ll_ty = str_arr_ty s in
(Ptr ll_ty, GGid gid), [gid, (ll_ty, GString s)]
let cast = GBitcast (Ptr ll_ty, GGid gid, Ptr I8) in
(Ptr I8, cast), [gid, (ll_ty, GString s)]
| CArr (u, cs) ->
let elts, gs = List.fold_right
@ -587,7 +613,9 @@ let rec cmp_gexp c (tc : TypeCtxt.t) (e:Ast.exp node) : Ll.gdecl * (Ll.gid * Ll.
let gid = gensym "global_arr" in
let arr_t = Struct [ I64; Array(len, ll_u) ] in
let arr_i = GStruct [ I64, GInt (Int64.of_int len); Array(len, ll_u), GArray elts ] in
(Ptr arr_t, GGid gid), (gid, (arr_t, arr_i))::gs
let final_t = Struct [ I64; Array(0, ll_u) ] in
let cast = GBitcast (Ptr arr_t, GGid gid, Ptr final_t) in
(Ptr final_t, cast), (gid, (arr_t, arr_i))::gs
(* STRUCT TASK: Complete this code that generates the global initializers for a struct value. *)
| CStruct (id, cs) ->

View file

@ -1,6 +1,8 @@
{
open Lexing
open Parser
module Range = Util.Range
open Range
exception Lexer_error of Range.t * string

View file

@ -1,10 +1,10 @@
open Ll
open Arg
open Assert
open Driver
open Util.Assert
open Oat.Driver
exception Ran_tests
let suite = ref (Studenttests.provided_tests @ Gradedtests.graded_tests)
let suite = ref (Studenttests.student_local_tests @ Gradedtests.graded_tests)
let execute_tests () =
Platform.configure_os ();
@ -13,7 +13,7 @@ let execute_tests () =
raise Ran_tests
let args =
[ ("-linux", Set Platform.linux, "use linux-style name mangling [must precede --test on linux]")
[ ("-linux", Set Platform.linux, "use linux-style name mangling [must preceed --test on linux]")
; ("--test", Unit execute_tests, "run the test suite, ignoring other files inputs")
; ("-op", Set_string Platform.output_path, "set the path to the output files directory [default='output']")
; ("-o", Set_string executable_filename, "set the name of the resulting executable [default='a.out']")
@ -21,10 +21,11 @@ let args =
; ("-c", Clear link, "stop after generating .o files; do not generate executables")
; ("--print-ll", Set print_ll_flag, "prints the program's LL code (after lowering to clang code if --clang-malloc is set)")
; ("--print-x86", Set print_x86_flag, "prints the program's assembly code")
; ("--clang", Set clang, "compiles to assembly using clang, not the 341 backend (implies --clang-malloc)")
; ("--print-regs", Set print_regs_flag, "prints the register usage statistics for x86 code")
; ("--clang", Set clang, "compiles to assembly using clang, not the 131 backend (implies --clang-malloc)")
; ("--execute-x86", Set execute_x86, "run the resulting executable file")
; ("-v", Set Platform.verbose, "enables more verbose compilation output")
]
]
let files = ref []
@ -33,7 +34,7 @@ let _ =
Platform.create_output_dir ();
try
Arg.parse args (fun filename -> files := filename :: !files)
"Compiler Design main test harness\n\
"cs131 main test harness\n\
USAGE: ./main.native [options] <files>\n\
see README for details about using the compiler";
Platform.configure_os ();

View file

@ -188,12 +188,14 @@ exp:
| i=INT { loc $startpos $endpos @@ CInt i }
| s=STRING { loc $startpos $endpos @@ CStr s }
| NEW t=ty LBRACKET RBRACKET LBRACE cs=separated_list(COMMA, exp) RBRACE
{ loc $startpos $endpos @@ CArr (t, cs) }
{ loc $startpos $endpos @@ CArr (t, cs) }
| NEW t=ty LBRACKET e1=exp RBRACKET
{ loc $startpos $endpos @@ NewArr(t, e1) }
| NEW t=UIDENT LBRACE cs=separated_list(SEMI, field) RBRACE
{ loc $startpos $endpos @@ CStruct(t, cs) }
| e=exp DOT id=IDENT { loc $startpos $endpos @@ Proj(e, id) }
| NEW t=ty LBRACKET e1=exp RBRACKET LBRACE u=IDENT ARROW e2=exp RBRACE
{ loc $startpos $endpos @@ NewArr(t, e1, u, e2) }
{ loc $startpos $endpos @@ NewArrInit(t, e1, u, e2) }
| id=IDENT { loc $startpos $endpos @@ Id id }
| e=exp LBRACKET i=exp RBRACKET
{ loc $startpos $endpos @@ Index (e, i) }

View file

@ -12,7 +12,7 @@ int64_t* oat_malloc(int64_t size) {
int64_t* oat_alloc_array (int64_t size) {
assert (size >= 0);
int64_t *arr = (int64_t*)malloc(sizeof(int64_t) * (size+1));
int64_t *arr = (int64_t*)calloc(size+1, sizeof(int64_t));
arr[0] = size;
return arr;
}
@ -117,7 +117,7 @@ void print_bool (int64_t i) {
}
}
extern int64_t program(int64_t argc, int64_t* oargv);
extern int64_t program(int64_t oargc, int64_t* oargv);
/*
* Convert the argv array into an Oat array of

View file

@ -7,7 +7,7 @@ open Tctxt
exception TypeError of string
let type_error (l : 'a node) err =
let type_error (l : 'a node) (err : string) =
let (_, (s, e), _) = l.loc in
raise (TypeError (Printf.sprintf "[%d, %d] %s" s e err))
@ -62,7 +62,7 @@ and subtype_ref (c : Tctxt.t) (t1 : Ast.rty) (t2 : Ast.rty) : bool =
according to the rules
- the function should fail using the "type_error" helper function if the
type is not well-formed
type is not well formed
- l is just an ast node that provides source location information for
generating error messages (it's only needed for the type_error generation)
@ -72,10 +72,17 @@ and subtype_ref (c : Tctxt.t) (t1 : Ast.rty) (t2 : Ast.rty) : bool =
let rec typecheck_ty (l : 'a Ast.node) (tc : Tctxt.t) (t : Ast.ty) : unit =
failwith "todo: implement typecheck_ty"
(* A helper function to determine whether a type allows the null value *)
let is_nullable_ty (t : Ast.ty) : bool =
match t with
| TNullRef _ -> true
| _ -> false
(* typechecking expressions ------------------------------------------------- *)
(* Typechecks an expression in the typing context c, returns the type of the
expression. This function should implement the inference rules given in the
oad.pdf specification. There, they are written:
oat.pdf specification. There, they are written:
H; G; L |- exp : t
@ -103,7 +110,7 @@ let rec typecheck_exp (c : Tctxt.t) (e : Ast.exp node) : Ast.ty =
(* statements --------------------------------------------------------------- *)
(* Typecheck a statement
This function should implement the statement typechecking rules from oat.pdf.
This function should implement the statment typechecking rules from oat.pdf.
Inputs:
- tc: the type context
@ -112,15 +119,19 @@ let rec typecheck_exp (c : Tctxt.t) (e : Ast.exp node) : Ast.ty =
Returns:
- the new type context (which includes newly declared variables in scope
after this statement
after this statement)
- A boolean indicating the return behavior of a statement:
false: might not return
true: definitely returns
in the branching statements, both branches must definitely return
in the branching statements, the return behavior of the branching
statement is the conjunction of the return behavior of the two
branches: both both branches must definitely return in order for
the whole statement to definitely return.
Intuitively: if one of the two branches of a conditional does not
contain a return statement, then the entier conditional statement might
contain a return statement, then the entire conditional statement might
not return.
looping constructs never definitely return
@ -143,18 +154,19 @@ let rec typecheck_stmt (tc : Tctxt.t) (s:Ast.stmt node) (to_ret:ret_ty) : Tctxt.
*)
(* Helper function to look for duplicate field names *)
let rec check_dups fs =
let rec check_dups (fs : field list) =
match fs with
| [] -> false
| h :: t -> (List.exists (fun x -> x.fieldName = h.fieldName) t) || check_dups t
let typecheck_tdecl (tc : Tctxt.t) id fs (l : 'a Ast.node) : unit =
let typecheck_tdecl (tc : Tctxt.t) (id : id) (fs : field list) (l : 'a Ast.node) : unit =
if check_dups fs
then type_error l ("Repeated fields in " ^ id)
else List.iter (fun f -> typecheck_ty l tc f.ftyp) fs
(* function declarations ---------------------------------------------------- *)
(* typecheck a function declaration
- ensures formal parameters are distinct
- extends the local context with the types of the formal parameters to the
function
- typechecks the body of the function (passing in the expected return type
@ -188,7 +200,8 @@ let typecheck_fdecl (tc : Tctxt.t) (f : Ast.fdecl) (l : 'a Ast.node) : unit =
NOTE: global initializers may mention function identifiers as
constants, but can't mention other global values *)
constants, but can mention only other global values that were declared earlier
*)
let create_struct_ctxt (p:Ast.prog) : Tctxt.t =
failwith "todo: create_struct_ctxt"

3
hw5/dune-project Normal file
View file

@ -0,0 +1,3 @@
(lang dune 2.9)
(name hw5)
(using menhir 2.1)

View file

@ -1,490 +0,0 @@
open Assert
open X86
open Driver
open Ll
open Backend
(* Do NOT modify this file -- we will overwrite it with our *)
(* own version when we test your project. *)
(* These tests will be used to grade your assignment *)
let fdecl_of_path path =
Platform.verb @@ Printf.sprintf "* processing file: %s\n" path;
let ll_ast = parse_ll_file path in
match ll_ast.Ll.fdecls with
| [_, fdecl] -> fdecl
| _ -> failwith "test expected one fdecl"
let exec_e2e_ast ll_ast args extra_files =
let output_path = !Platform.output_path in
let dot_s_file = Platform.gen_name output_path "test" ".s" in
let exec_file = Platform.gen_name output_path "exec" "" in
let asm_ast = Backend.compile_prog ll_ast in
let asm_str = X86.string_of_prog asm_ast in
let _ = Driver.write_file dot_s_file asm_str in
let _ = Platform.link (dot_s_file::extra_files) exec_file in
let result = Driver.run_executable args exec_file in
let _ = Platform.sh (Printf.sprintf "rm -f %s %s" dot_s_file exec_file) Platform.ignore_error in
let _ = Platform.verb @@ Printf.sprintf "** Executable exited with: %d\n" result in
Int64.of_int result
let exec_e2e_file path args =
let ast = Driver.parse_ll_file path in
exec_e2e_ast ast args []
let io_test path args =
let ll_ast = Driver.parse_ll_file path in
let output_path = !Platform.output_path in
let dot_s_file = Platform.gen_name output_path "test" ".s" in
let exec_file = Platform.gen_name output_path "exec" "" in
let tmp_file = Platform.gen_name output_path "tmp" ".txt" in
let asm_ast = Backend.compile_prog ll_ast in
let asm_str = X86.string_of_prog asm_ast in
let _ = Driver.write_file dot_s_file asm_str in
let _ = Platform.link (dot_s_file::["cinterop.c"]) exec_file in
let args = String.concat " " args in
let result = Driver.run_program args exec_file tmp_file in
let _ = Platform.sh (Printf.sprintf "rm -f %s %s %s" dot_s_file exec_file tmp_file) Platform.ignore_error in
let _ = Platform.verb @@ Printf.sprintf "** Executable output:\n%s\n" result in
result
let c_link_test c_files path args =
let ll_ast = Driver.parse_ll_file path in
let output_path = !Platform.output_path in
let dot_s_file = Platform.gen_name output_path "test" ".s" in
let exec_file = Platform.gen_name output_path "exec" "" in
let asm_ast = Backend.compile_prog ll_ast in
let asm_str = X86.string_of_prog asm_ast in
let _ = Driver.write_file dot_s_file asm_str in
let _ = Platform.link (dot_s_file::c_files) exec_file in
let args = String.concat " " args in
let result = Driver.run_executable args exec_file in
let _ = Platform.sh (Printf.sprintf "rm -f %s %s" dot_s_file exec_file) Platform.ignore_error in
Int64.of_int result
let oat_file_test path args =
let () = Platform.verb @@ Printf.sprintf "** Processing: %s\n" path in
let output_path = !Platform.output_path in
let dot_ll_file = Platform.gen_name output_path "test" ".ll" in
let exec_file = Platform.gen_name output_path "exec" "" in
let tmp_file = Platform.gen_name output_path "tmp" ".txt" in
let oat_ast = parse_oat_file path in
Typechecker.typecheck_program oat_ast;
let ll_ast = Frontend.cmp_prog oat_ast in
let ll_str = Driver.string_of_ll_ast path ll_ast in
let () = write_file dot_ll_file ll_str in
let () = Platform.link (dot_ll_file::["runtime.c"]) exec_file in
let result = Driver.run_program args exec_file tmp_file in
let () = Platform.sh (Printf.sprintf "rm -f %s %s %s" dot_ll_file exec_file tmp_file) Platform.ignore_error in
let () = Platform.verb @@ Printf.sprintf "** Executable output:\n%s\n" result in
result
let oat_tc_ok_file_test path =
let _ = Platform.verb @@ Printf.sprintf "** OAT Typechecker OK Processing: %s\n" path in
let oat_ast = parse_oat_file path in
let _= Typechecker.typecheck_program oat_ast in
()
let oat_tc_err_file_test path err =
let _ = Platform.verb @@ Printf.sprintf "** OAT Typechecker Error Processing: %s\n" path in
let oat_ast = parse_oat_file path in
try
let _ = Typechecker.typecheck_program oat_ast in
failwith @@ Printf.sprintf "Expected type error: %s" err
with
| Typechecker.TypeError s ->
if s = err then () else
failwith @@ Printf.sprintf "Expected type error: %s but got %s" err s
let executed tests =
List.map (fun (fn, ans) ->
fn, assert_eqf (fun () -> exec_e2e_file fn "") ans)
tests
let executed_oat_file tests =
List.map (fun (path, args, ans) ->
(path ^ " args: " ^ args), assert_eqf (fun () -> oat_file_test path args) ans)
tests
let executed_tc_ok_file tests =
List.map (fun path ->
("typechecking: " ^ path, fun () -> oat_tc_ok_file_test path)) tests
let executed_tc_err_file tests =
List.map (fun (path, err) ->
("typechecking: " ^ path, fun () -> oat_tc_err_file_test path err)) tests
let executed_io tests =
List.map (fun (fn, args, ans) ->
(fn ^ ":" ^ (String.concat " " args)), assert_eqf (fun () -> io_test fn args) ans)
tests
let executed_c_link tests =
List.map (fun (c_file, fn, args, ans) ->
(fn ^ ":" ^ (String.concat " " args)), assert_eqf (fun () -> c_link_test c_file fn args) ans)
tests
let typecheck path () =
let () = Platform.verb @@ Printf.sprintf "** Processing: %s\n" path in
let oat_ast = parse_oat_file path in
Typechecker.typecheck_program oat_ast
let typecheck_error (a : assertion) () =
try a (); failwith "Should have a type error" with Typechecker.TypeError s -> ()
let typecheck_correct (a : assertion) () =
try a () with Typechecker.TypeError s -> failwith "Should not have had a type error"
let typecheck_file_error tests =
List.map (fun p -> p, typecheck_error (typecheck p)) tests
let typecheck_file_correct tests =
List.map (fun p -> p, typecheck_correct (typecheck p)) tests
let unit_tests = [
"subtype_stringQ_stringQ",
(fun () ->
if Typechecker.subtype Tctxt.empty (TNullRef RString) (TNullRef RString) then ()
else failwith "should not fail")
; ("no_subtype_stringQ_stringQ",
(fun () ->
if Typechecker.subtype Tctxt.empty (TNullRef RString) (TRef RString) then
failwith "should not succeed" else ())
)
]
let hw4_easiest_tests = [
("oatprograms/easyrun1.oat", "", "17");
("oatprograms/easyrun2.oat", "", "35");
("oatprograms/easyrun3.oat", "", "73");
("oatprograms/easyrun4.oat", "", "6");
("oatprograms/easyrun5.oat", "", "212");
("oatprograms/easyrun6.oat", "", "9");
("oatprograms/easyrun7.oat", "", "23");
("oatprograms/easyrun8.oat", "", "96");
("oatprograms/easyrun9.oat", "", "236");
]
let hw4_globals_tests = [
("oatprograms/globals1.oat", "", "42");
("oatprograms/globals2.oat", "", "17");
("oatprograms/globals3.oat", "", "17");
("oatprograms/globals4.oat", "", "5");
("oatprograms/globals5.oat", "", "17");
("oatprograms/globals6.oat", "", "15");
]
let hw4_path_tests = [
("oatprograms/path1.oat", "", "17");
("oatprograms/path2.oat", "", "35");
("oatprograms/path3.oat", "", "3");
("oatprograms/arrayargs1.oat", "", "17");
("oatprograms/arrayargs2.oat", "", "17");
("oatprograms/arrayargs3.oat", "", "34");
]
let hw4_easy_tests = [
("oatprograms/run26.oat", "", "0");
("oatprograms/run27.oat", "", "99");
("oatprograms/run28.oat", "", "18");
("oatprograms/run29.oat", "", "1");
("oatprograms/run30.oat", "", "9");
("oatprograms/run31.oat", "", "9");
("oatprograms/run13.oat", "", "1");
("oatprograms/run32.oat", "", "33");
("oatprograms/run21.oat", "", "99");
("oatprograms/run33.oat", "", "1");
("oatprograms/run34.oat", "", "66");
("oatprograms/run38.oat", "", "31");
("oatprograms/run39.oat", "a", "2");
("oatprograms/run40.oat", "", "8");
("oatprograms/run41.oat", "", "3");
("oatprograms/run42.oat", "", "2");
("oatprograms/run49.oat", "", "abc0");
("oatprograms/run50.oat", "", "abcde0");
("oatprograms/run60.oat", "", "85");
("oatprograms/run61.oat", "", "3410");
]
let hw4_medium_tests = [
("oatprograms/fact.oat", "", "1200");
("oatprograms/run1.oat", "", "153");
("oatprograms/run2.oat", "", "6");
("oatprograms/run8.oat", "", "2");
("oatprograms/run9.oat", "", "4");
("oatprograms/run10.oat", "", "5");
("oatprograms/run11.oat", "", "7");
("oatprograms/run14.oat", "", "16");
("oatprograms/run15.oat", "", "19");
("oatprograms/run16.oat", "", "13");
("oatprograms/run22.oat", "", "abc0");
("oatprograms/run23.oat", "", "1230");
("oatprograms/run25.oat", "", "nnn0");
("oatprograms/run46.oat", "", "420");
("oatprograms/run47.oat", "", "3");
("oatprograms/run48.oat", "", "11");
("oatprograms/lib4.oat", "", "53220");
("oatprograms/lib5.oat", "", "20");
("oatprograms/lib6.oat", "", "56553");
("oatprograms/lib7.oat", "", "53");
("oatprograms/lib8.oat", "", "Hello world!0");
("oatprograms/lib9.oat", "a b c d", "abcd5");
("oatprograms/lib11.oat", "", "45");
("oatprograms/lib14.oat", "", "~}|{zyxwvu0");
("oatprograms/lib15.oat", "123456789", "456780");
]
let hw4_hard_tests = [
("oatprograms/fac.oat", "", "120");
("oatprograms/qsort.oat", "", "kpyf{shomfhkmopsy{255");
("oatprograms/bsort.oat", "", "y}xotnuw notuwxy}255");
("oatprograms/msort.oat", "", "~}|{zyxwvu uvwxyz{|}~ 0");
("oatprograms/msort2.oat", "", "~}|{zyxwvu uvwxyz{|}~ 0");
("oatprograms/selectionsort.oat", "", "01253065992000");
("oatprograms/matrixmult.oat", "", "19 16 13 23 \t5 6 7 6 \t19 16 13 23 \t5 6 7 6 \t0");
]
let hw4_old_student_tests = [
("oatprograms/binary_search.oat", "", "Correct!0")
; ("oatprograms/xor_shift.oat", "", "838867572\n22817190600")
; ("oatprograms/sieve.oat", "", "25")
; ("oatprograms/count_sort.oat", "", "AFHZAAEYC\nAAACEFHYZ0")
; ("oatprograms/determinant_size2.oat", "", "94")
; ("oatprograms/fibo.oat", "", "0")
; ("oatprograms/bubble_sort.oat", "", "1")
; ("oatprograms/heap.oat", "", "1")
; ("oatprograms/binary_gcd.oat", "", "3")
; ("oatprograms/lfsr.oat", "", "TFTF FFTT0")
; ("oatprograms/gnomesort.oat", "", "01253065992000")
; ("oatprograms/josh_joyce_test.oat", "", "0")
; ("oatprograms/conquest.oat", "", "My name is Jeff...\nCharizard is the BEST Pokemon ever!!!11")
; ("oatprograms/gcd.oat", "", "16")
; ("oatprograms/lcs.oat", "", "OAT0")
; ("oatprograms/insertion_sort.oat", "", "42")
; ("oatprograms/maxsubsequence.oat", "", "107")
]
let hw4_type_error_tests = [
"oatprograms/run3.oat"
; "oatprograms/run5.oat"
; "oatprograms/run35.oat"
; "oatprograms/run43.oat"
; "oatprograms/run44.oat"
; "oatprograms/run45.oat"
]
let struct_tests = [
("hw5programs/compile_assign_struct.oat", "", "16");
("hw5programs/compile_basic_struct.oat", "", "7");
("hw5programs/compile_global_struct.oat", "", "254");
("hw5programs/compile_nested_struct.oat", "", "10");
("hw5programs/compile_return_struct.oat", "", "0");
("hw5programs/compile_struct_array.oat", "", "15");
("hw5programs/compile_struct_fptr.oat", "", "7");
("hw5programs/compile_various_fields.oat", "", "hello253");
]
let fptr_tests = [
("hw5programs/compile_array_fptr.oat", "", "2");
("hw5programs/compile_func_argument.oat", "", "4");
("hw5programs/compile_global_fptr.oat", "", "7");
("hw5programs/compile_global_fptr_unordered.oat", "", "2");
("hw5programs/compile_scall_fptr.oat", "", "4");
("hw5programs/compile_var_fptr.oat", "", "1");
("hw5programs/compile_local_fptr.oat", "", "5");
("hw5programs/compile_function_shadow.oat", "", "12");
("hw5programs/compile_global_struct_fptr.oat", "", "20");
("hw5programs/compile_builtin_argument.oat", "", "abab0");
]
let typecheck_subtyping_tests =
[ "hw5programs/tc_subtyping1.oat"
; "hw5programs/tc_subtyping2.oat"
; "hw5programs/tc_subtyping3.oat"
; "hw5programs/tc_subtyping4.oat"
; "hw5programs/tc_subtyping5.oat"
; "hw5programs/tc_subtyping6.oat"
; "hw5programs/tc_subtyping7.oat"
; "hw5programs/tc_subtyping8.oat"
; "hw5programs/tc_subtyping9.oat"
]
let typecheck_subtyping_error_tests =
[ "hw5programs/tc_subtyping_err1.oat"
; "hw5programs/tc_subtyping_err2.oat"
; "hw5programs/tc_subtyping_err3.oat"
; "hw5programs/tc_subtyping_err4.oat"
; "hw5programs/tc_subtyping_err5.oat"
; "hw5programs/tc_subtyping_err6.oat"
; "hw5programs/tc_subtyping_err7.oat"
; "hw5programs/tc_subtyping_err8.oat"
]
let typecheck_statement_error_tests =
[ "hw5programs/tc_error_early_return.oat";
"hw5programs/tc_error_early_return_void.oat";
"hw5programs/tc_error_return_wrong.oat";
"hw5programs/tc_error_while_nonbool.oat";
"hw5programs/tc_error_while.oat";
"hw5programs/tc_error_if_nonbool.oat";
"hw5programs/tc_error_if.oat";
"hw5programs/tc_error_for.oat";
"hw5programs/tc_error_void.oat";
"hw5programs/tc_error_assign_void.oat";
"hw5programs/tc_error_scall_nonvoid.oat";
]
let typecheck_correct_statement_tests =
[ "hw5programs/tc_correct_while.oat";
"hw5programs/tc_correct_for.oat";
"hw5programs/tc_correct_if.oat";
"hw5programs/tc_correct_void.oat"
]
let typecheck_error_expression_tests =
[ "hw5programs/tc_error_binop1.oat";
"hw5programs/tc_error_binop2.oat";
"hw5programs/tc_error_binop3.oat";
"hw5programs/tc_error_call1.oat";
"hw5programs/tc_error_call2.oat";
"hw5programs/tc_error_unop1.oat";
"hw5programs/tc_error_array1.oat";
"hw5programs/tc_error_array2.oat";
"hw5programs/tc_error_null.oat";
]
let typecheck_error_struct_tests =
[ "hw5programs/tc_error_struct_proj.oat";
"hw5programs/tc_error_struct1.oat";
"hw5programs/tc_error_struct2.oat";
"hw5programs/tc_error_struct3.oat";
"hw5programs/tc_error_struct4.oat";
"hw5programs/tc_error_struct_dup.oat";
"hw5programs/tc_error_struct.oat";
"hw5programs/tc_error_dupstruct.oat";
"hw5programs/tc_error_struct_unbound.oat";
]
let typecheck_error_global_tests =
[ "hw5programs/tc_error_global_dup.oat";
"hw5programs/tc_error_global.oat";
"hw5programs/tc_error_func_redeclaration.oat";
"hw5programs/tc_error_func_assign.oat";
"hw5programs/tc_error_overwrite.oat";
"hw5programs/tc_error_global_fptr_scope.oat";
"hw5programs/tc_error_function_no_shadow.oat";
"hw5programs/tc_correct_null.oat";
]
let typecheck_correct_other_tests =
[ "hw5programs/tc_correct_array.oat";
"hw5programs/tc_correct_call.oat";
"hw5programs/tc_correct_fptr.oat";
"hw5programs/tc_correct_global.oat";
"hw5programs/tc_correct_struct.oat";
"hw5programs/tc_correct_struct_fptr.oat";
"hw5programs/tc_correct_void.oat";
"hw5programs/tc_correct_local_redeclaration.oat";
"hw5programs/tc_correct_fptr_array.oat";
]
let typecheck_error_null_not_null_tests =
hw4_type_error_tests
let fptr_tests = [
("hw5programs/compile_array_fptr.oat", "", "2");
("hw5programs/compile_func_argument.oat", "", "4");
("hw5programs/compile_global_fptr.oat", "", "7");
("hw5programs/compile_global_fptr_unordered.oat", "", "2");
("hw5programs/compile_scall_fptr.oat", "", "4");
("hw5programs/compile_var_fptr.oat", "", "1");
("hw5programs/compile_local_fptr.oat", "", "5");
("hw5programs/compile_function_shadow.oat", "", "12");
("hw5programs/compile_global_struct_fptr.oat", "", "20");
("hw5programs/compile_builtin_argument.oat", "", "abab0");
]
let tc_ok_tests = [
"hw5programs/tc_struct_ok.oat"
; "hw5programs/tc_func_ret_ok.oat"
; "hw5programs/tc_func_arg_ok.oat"
; "hw5programs/tc_ifq1.oat"
; "oatprograms/tc_ok1.oat"
; "oatprograms/tc_ok2.oat"
; "oatprograms/tc_ok4.oat"
; "oatprograms/tc_ok5.oat"
; "oatprograms/tc_ok6.oat"
; "oatprograms/tc_ok7.oat"
; "oatprograms/tc_ok8.oat"
; "hw5programs/tc_arrow.oat"
; "hw5programs/tc_arrow_null.oat"
; "hw5programs/tc_arrow_null_rec.oat"
]
let tc_err_tests = [
"hw5programs/tc_null_array_err.oat"
; "hw5programs/tc_struct_err.oat"
; "hw5programs/tc_func_ret_err.oat"
; "hw5programs/tc_func_arg_err.oat"
; "hw5programs/tc_array_err.oat"
; "hw5programs/tc_struct_field_err.oat"
; "hw5programs/tc_recursive_struct_err.oat"
; "hw5programs/tc_ifq_err1.oat"
]
let typecheck_tests : suite = [
GradedTest("subtype unit tests", 3, unit_tests);
GradedTest("tc subtyping tests", 4, typecheck_file_correct typecheck_subtyping_tests);
GradedTest("tc subtyping error tests", 4, typecheck_file_error typecheck_subtyping_error_tests);
GradedTest("tc statement error tests", 5, typecheck_file_error typecheck_statement_error_tests);
GradedTest("tc statement correct tests", 5, typecheck_file_correct typecheck_correct_statement_tests);
GradedTest("tc other correct tests", 5, typecheck_file_correct typecheck_correct_other_tests);
GradedTest("tc null/not null error tests", 5, typecheck_file_error typecheck_error_null_not_null_tests);
GradedTest("tc expression error tests", 5, typecheck_file_error typecheck_error_expression_tests);
GradedTest("tc struct/global error tests", 5, typecheck_file_error (typecheck_error_struct_tests @ typecheck_error_global_tests));
GradedTest("extra tc err tests", 5, typecheck_file_error tc_err_tests);
]
let student_tests = []
let hw5_tests : suite = [
GradedTest("tc ok tests", 10, executed_tc_ok_file tc_ok_tests)
; GradedTest("struct tests", 10, executed_oat_file struct_tests)
; GradedTest("fptr tests", 4, executed_oat_file fptr_tests)
; GradedTest("hidden tests", 20, executed_oat_file student_tests)
]
let hw4_tests =
hw4_easiest_tests
@ hw4_globals_tests
@ hw4_path_tests
@ hw4_easy_tests
@ hw4_medium_tests
@ hw4_hard_tests
@ hw4_old_student_tests
let functionality_tests : suite = [GradedTest("functionality tests from HW04", 10, executed_oat_file hw4_tests)]
let graded_tests : suite =
typecheck_tests @
hw5_tests @
functionality_tests

13
hw5/hw4programs/abs.oat Normal file
View file

@ -0,0 +1,13 @@
int abs(int x) {
if (x < 0) {
return -x;
} else if (x > 0) {
return x;
} else {
return 0;
}
}
int program (int argc, string[] argv) {
print_int(abs(10) + abs(-10) + abs(0));
return 0;
}

View file

@ -0,0 +1,8 @@
int foo(int x) {
x = x + 1;
return x;
}
int program (int argc, string[] argv) {
return foo(17);
}

View file

@ -7,8 +7,8 @@ int[] f(int[] x, int[] y, bool b) {
}
int program (int argc, string[] argv) {
var x = new int[3]{i -> 0};
var y = new int[3]{i -> 0};
var x = new int[3];
var y = new int[3];
f(x, y, true)[0] = 17;
return x[0];
}

View file

@ -51,7 +51,7 @@ bool binary_search (int[] input, int key, int min, int max) {
}
int program (int argc, string[] argv) {
var test_array = new int[100]{i->0};
var test_array = new int[100];
for (var i=0; i < 100; i=i+1;) { test_array[i] = 2 * i + 1; }
var even = binary_search (test_array, 80, 0, 99);
var odd = binary_search (test_array, 81, 0, 99);

View file

@ -20,7 +20,7 @@ void bubble_sort(int[] numbers, int array_size)
}
int program (int argc, string[] argv) {
var a = new int[8]{i -> 0};
var a = new int[8];
a[0] = 121;
a[1] = 125;

View file

@ -23,7 +23,7 @@ int[] count_sort(int[] arr, int len) {
var min = min(arr, len);
var max = max(arr, len);
var counts = new int[max - min + 1]{i->0};
var counts = new int[max - min + 1];
for (var i = 0; i < len; i = i + 1;) {
counts[arr[i] - min] = counts[arr[i] - min] + 1;
@ -32,7 +32,7 @@ int[] count_sort(int[] arr, int len) {
var i = min;
var j = 0;
var out = new int[len]{i2->0};
var out = new int[len];
while (i <= max) {

View file

@ -0,0 +1,14 @@
global i = 19;
global b1 = true;
global b2 = false;
global str = "This is a string!";
global arr1 = new int[]{0,1,2};
global arr2 = new int[][]{ new int[]{10,11}, new int[]{20,21}, new int[]{30,31}};
global arr3 = new string[]{"String1", "String2", "String3"};
global arr4 = new string[][]
{
new string[]{"String00","String01"},
new string[]{"String10","String11"},
new string[]{"String20","String21"}
};

View file

@ -1,8 +1,7 @@
global j = int[]{1,2,3,4};
global j = new int[]{1,2,3,4};
int[] f () {
var a = new int[][]{1, 2};
var i = new int[4];
var arr1 = new int[3];
var arr2 = new int[][3];
return new int[2];
}

View file

@ -1,6 +1,6 @@
int program (int argc, string[] argv) {
if(6 != 5) {
return ~(5 << 17 >> 2 >>> 10) * 2 - 100 + 6;
return ~(5 >> --6 << 9 >>> 10) * 2 - 100 + 6;
} else {
return 2;
}

View file

@ -1,52 +1,52 @@
global float_len = 2;
int[] determine_shift(int[] float)
{
var dec = float[1];
var count = 0;
while(dec > 0)
{
var temp = float[0];
float[0] = temp << 1;
dec = dec >>> 1;
count = count + 1;
}
var list = new int[2];
list[0] = float[0] + float[1];
list[1] = count;
return list;
}
int[] multiply_floats(int[] f1, int[] f2)
{
var f1_shifted = determine_shift(f1);
var f2_shifted = determine_shift(f2);
var product = f1_shifted[0] * f2_shifted[0];
var num_left_shifts = f1_shifted[1] + f2_shifted[1];
var remainder = 0;
for(var i = 0; i < num_left_shifts; i=i+1;)
{
var lsb = product [&] 1;
var shifted_lsb = lsb << i;
product = product >>> 1;
remainder = remainder + shifted_lsb;
}
var ans = new int[2];
ans[0] = product;
ans[1] = remainder;
return ans;
}
int program(int argc, string[] argv)
{
var pi = new int[2];
pi[0] = 3;
pi[1] = 14159;
var diameter = new int[2];
diameter[0] = 20;
diameter[1] = 17;
var prod = multiply_floats(pi, diameter);
print_int(prod[0]);
print_string(".");
print_int(prod[1]);
return 0;
global float_len = 2;
int[] determine_shift(int[] float)
{
var dec = float[1];
var count = 0;
while(dec > 0)
{
var temp = float[0];
float[0] = temp << 1;
dec = dec >>> 1;
count = count + 1;
}
var list = new int[2];
list[0] = float[0] + float[1];
list[1] = count;
return list;
}
int[] multiply_floats(int[] f1, int[] f2)
{
var f1_shifted = determine_shift(f1);
var f2_shifted = determine_shift(f2);
var product = f1_shifted[0] * f2_shifted[0];
var num_left_shifts = f1_shifted[1] + f2_shifted[1];
var remainder = 0;
for(var i = 0; i < num_left_shifts; i=i+1;)
{
var lsb = product [&] 1;
var shifted_lsb = lsb << i;
product = product >>> 1;
remainder = remainder + shifted_lsb;
}
var ans = new int[2];
ans[0] = product;
ans[1] = remainder;
return ans;
}
int program(int argc, string[] argv)
{
var pi = new int[2];
pi[0] = 3;
pi[1] = 14159;
var diameter = new int[2];
diameter[0] = 20;
diameter[1] = 17;
var prod = multiply_floats(pi, diameter);
print_int(prod[0]);
print_string(".");
print_int(prod[1]);
return 0;
}

View file

@ -0,0 +1,8 @@
global arr = new int[] {};
int program (int argc, string[] argv) {
var x = new int[3];
arr = x;
x[2] = 3;
return arr[2];
}

View file

@ -1,5 +1,5 @@
int[] insert(int[] partial, int len, int insertee) {
var inserted = new int[len+1]{i->0};
var inserted = new int[len+1];
for (var i=0; i < len+1; i=i+1;) { inserted[i] = -1; }
var not_yet_inserted = true;
if (insertee < partial[0]) {

View file

@ -20,7 +20,7 @@ void print_lfsr(bool[] lfsr_register, int len) {
int program(int argc, string[] argv) {
/* Initialize the working register */
var lfsr_register = new bool[lfsr_length]{i->false};
var lfsr_register = new bool[lfsr_length];
for (var i=0; i < lfsr_length; i=i+1;) {
lfsr_register[i] = lfsr_init_values[i];
}

View file

@ -1,6 +1,9 @@
string sub (string str, int start, int len) {
var arr = array_of_string(str);
var r = new int[len]{i -> arr[i+start]};
var r = new int[len];
for (var i = 0; i < len; i = i + 1;) {
r[i] = arr[i+start];
}
return string_of_array (r);
}

View file

@ -44,7 +44,10 @@ int program (int argc, string[] argv) {
new int[]{1, 1, 1, 0},
new int[]{0, 0, 0, 0} };
var new_board = new int[][4];
var new_board = new int[][]{ new int[]{0, 0, 0, 0},
new int[]{0, 0, 0, 0},
new int[]{0, 0, 0, 0},
new int[]{0, 0, 0, 0} };
for (var i=0; i < 4; i=i+1;) {
new_board[i] = new int[4];
for (var j=0; j < 4; j=j+1;) { new_board[i][j] = val_at(board, i,j); }

View file

@ -1,5 +1,5 @@
int maxsum(int[] arr, int size) {
var maxarr = new int[size]{i->0};
var maxarr = new int[size];
var maxs = 0;
maxarr[0] = arr[0];
for(var i = 0; i < size; i = i+1;){

View file

@ -27,7 +27,7 @@ void merge(int[] a, int low, int high, int mid)
var i=0;
var j=0;
var k=0;
var c=new int[50]{i1->0};
var c=new int[50];
i=low;
j=mid+1;
k=low;

View file

@ -27,7 +27,7 @@ void merge(int[] a, int low, int high, int mid)
var i=0;
var j=0;
var k=0;
var c=new int[50]{i2->0};
var c=new int[50];
i=low;
j=mid+1;
k=low;

View file

@ -1,39 +1,39 @@
int mod (int a, int b) {
var t = a;
while (t - b >= 0) {
t = t - b;
}
return t;
}
int div (int a, int b) {
var result = 0;
var num = a;
var denom = b;
while (num > 0) {
num = num - denom;
result = result + 1;
}
return result;
}
int no_of_factors(int n) {
var num_fact = 1;
var input = n;
for (var i = 2; i * i < input + 1; i=i+1;) {
var power = 0;
while (mod(n, i) == 0) {
n = div(n, i);
power = power + 1;
}
num_fact = num_fact * (power + 1);
}
if (n > 1) {
num_fact = num_fact * 2;
}
return num_fact;
}
int program (int argc, string[] argv) {
return no_of_factors(6400);
}
int mod (int a, int b) {
var t = a;
while (t - b >= 0) {
t = t - b;
}
return t;
}
int div (int a, int b) {
var result = 0;
var num = a;
var denom = b;
while (num > 0) {
num = num - denom;
result = result + 1;
}
return result;
}
int no_of_factors(int n) {
var num_fact = 1;
var input = n;
for (var i = 2; i * i < input + 1; i=i+1;) {
var power = 0;
while (mod(n, i) == 0) {
n = div(n, i);
power = power + 1;
}
num_fact = num_fact * (power + 1);
}
if (n > 1) {
num_fact = num_fact * 2;
}
return num_fact;
}
int program (int argc, string[] argv) {
return no_of_factors(6400);
}

Some files were not shown because too many files have changed in this diff Show more