From 9224001a22f603b6dc9fa155f32f0c970bb479ab Mon Sep 17 00:00:00 2001 From: jmug Date: Fri, 24 Jan 2025 21:10:31 -0800 Subject: [PATCH] Update hw5 to a newer version. Signed-off-by: jmug --- hw5/.ocamlformat | 2 + hw5/.ocamlinit | 1 + hw5/Makefile | 31 +- hw5/README | 69 --- hw5/README.md | 73 +++ hw5/{ => bin}/ast.ml | 4 +- hw5/{ => bin}/astlib.ml | 13 +- hw5/{ => bin}/backend.ml | 2 + hw5/{ => bin}/driver.ml | 6 +- hw5/bin/dune | 29 ++ hw5/{ => bin}/frontend.ml | 98 ++-- hw5/{ => bin}/lexer.mll | 2 + hw5/{ => bin}/main.ml | 15 +- hw5/{ => bin}/parser.mly | 6 +- hw5/{ => bin}/runtime.c | 4 +- hw5/{ => bin}/tctxt.ml | 0 hw5/{ => bin}/typechecker.ml | 33 +- hw5/dune-project | 3 + hw5/gradedtests.ml | 490 ------------------ hw5/hw4programs/abs.oat | 13 + hw5/hw4programs/argassign.oat | 8 + .../arrayargs.oat | 0 .../arrayargs1.oat | 0 .../arrayargs2.oat | 4 +- .../arrayargs3.oat | 0 .../arrayargs4.oat | 0 .../binary_gcd.oat | 0 .../binary_search.oat | 2 +- hw5/{oatprograms => hw4programs}/bsort.oat | 2 +- .../calculator.oat | 0 .../count_sort.oat | 4 +- hw5/{oatprograms => hw4programs}/easy_p1.oat | 0 hw5/{oatprograms => hw4programs}/easy_p2.oat | 0 hw5/{oatprograms => hw4programs}/easy_p3.oat | 0 hw5/{oatprograms => hw4programs}/easy_p4.oat | 0 hw5/hw4programs/easy_p5.oat | 14 + hw5/{oatprograms => hw4programs}/easy_p6.oat | 0 hw5/{oatprograms => hw4programs}/easy_p7.oat | 3 +- hw5/{oatprograms => hw4programs}/easyrun1.oat | 0 .../easyrun10.oat | 0 hw5/{oatprograms => hw4programs}/easyrun2.oat | 0 hw5/{oatprograms => hw4programs}/easyrun3.oat | 0 hw5/{oatprograms => hw4programs}/easyrun4.oat | 0 hw5/{oatprograms => hw4programs}/easyrun5.oat | 0 hw5/{oatprograms => hw4programs}/easyrun6.oat | 0 hw5/{oatprograms => hw4programs}/easyrun7.oat | 0 hw5/{oatprograms => hw4programs}/easyrun8.oat | 2 +- hw5/{oatprograms => hw4programs}/easyrun9.oat | 0 hw5/{oatprograms => hw4programs}/fac.oat | 0 hw5/{oatprograms => hw4programs}/fact.oat | 0 hw5/{oatprograms => hw4programs}/fibo.oat | 0 .../float_multiply.oat | 102 ++-- hw5/{oatprograms => hw4programs}/gcd.oat | 0 hw5/{oatprograms => hw4programs}/globals1.oat | 0 hw5/{oatprograms => hw4programs}/globals2.oat | 0 hw5/{oatprograms => hw4programs}/globals3.oat | 0 hw5/{oatprograms => hw4programs}/globals4.oat | 0 hw5/{oatprograms => hw4programs}/globals5.oat | 0 hw5/{oatprograms => hw4programs}/globals6.oat | 0 hw5/hw4programs/globals7.oat | 8 + .../gnomesort.oat | 0 hw5/{oatprograms => hw4programs}/hashcode.oat | 0 hw5/{oatprograms => hw4programs}/heap.oat | 0 .../insertion_sort.oat | 2 +- hw5/{oatprograms => hw4programs}/is_prime.oat | 0 .../josh_joyce_test.oat | 0 hw5/{oatprograms => hw4programs}/kmp.oat | 0 hw5/{oatprograms => hw4programs}/lcs.oat | 0 .../leastsquare.oat | 0 hw5/{oatprograms => hw4programs}/lfsr.oat | 2 +- hw5/{oatprograms => hw4programs}/lfsr2.oat | 0 hw5/{oatprograms => hw4programs}/lib10.oat | 0 hw5/{oatprograms => hw4programs}/lib11.oat | 0 hw5/{oatprograms => hw4programs}/lib12.oat | 0 hw5/{oatprograms => hw4programs}/lib13.oat | 0 hw5/{oatprograms => hw4programs}/lib14.oat | 0 hw5/{oatprograms => hw4programs}/lib15.oat | 5 +- hw5/{oatprograms => hw4programs}/lib2.oat | 0 hw5/{oatprograms => hw4programs}/lib3.oat | 0 hw5/{oatprograms => hw4programs}/lib4.oat | 0 hw5/{oatprograms => hw4programs}/lib5.oat | 0 hw5/{oatprograms => hw4programs}/lib6.oat | 0 hw5/{oatprograms => hw4programs}/lib7.oat | 0 hw5/{oatprograms => hw4programs}/lib8.oat | 0 hw5/{oatprograms => hw4programs}/lib9.oat | 0 hw5/{oatprograms => hw4programs}/life.oat | 5 +- .../matrixmult.oat | 0 .../maxsubsequence.oat | 2 +- hw5/{oatprograms => hw4programs}/msort.oat | 2 +- hw5/{oatprograms => hw4programs}/msort2.oat | 2 +- .../no_of_fac.oat | 78 +-- hw5/{oatprograms => hw4programs}/path1.oat | 0 hw5/{oatprograms => hw4programs}/path2.oat | 0 hw5/{oatprograms => hw4programs}/path3.oat | 0 hw5/{oatprograms => hw4programs}/phase2_1.oat | 0 hw5/{oatprograms => hw4programs}/qs_bs.oat | 0 hw5/{oatprograms => hw4programs}/qsort.oat | 0 .../regalloctest.oat | 0 .../regalloctest2.oat | 0 hw5/{oatprograms => hw4programs}/regex.oat | 0 hw5/{oatprograms => hw4programs}/reverse.oat | 0 .../rod_cutting.oat | 0 hw5/{oatprograms => hw4programs}/run1.oat | 0 hw5/{oatprograms => hw4programs}/run10.oat | 0 hw5/{oatprograms => hw4programs}/run11.oat | 0 hw5/{oatprograms => hw4programs}/run13.oat | 0 hw5/{oatprograms => hw4programs}/run14.oat | 8 +- hw5/hw4programs/run15.oat | 20 + hw5/hw4programs/run16.oat | 9 + hw5/{oatprograms => hw4programs}/run18.oat | 0 hw5/{oatprograms => hw4programs}/run19.oat | 0 hw5/{oatprograms => hw4programs}/run2.oat | 0 hw5/{oatprograms => hw4programs}/run20.oat | 0 hw5/{oatprograms => hw4programs}/run21.oat | 0 hw5/{oatprograms => hw4programs}/run22.oat | 0 hw5/{oatprograms => hw4programs}/run23.oat | 0 hw5/{oatprograms => hw4programs}/run24.oat | 0 hw5/{oatprograms => hw4programs}/run25.oat | 2 +- hw5/{oatprograms => hw4programs}/run26.oat | 0 hw5/{oatprograms => hw4programs}/run27.oat | 0 hw5/{oatprograms => hw4programs}/run28.oat | 0 hw5/{oatprograms => hw4programs}/run29.oat | 0 hw5/{oatprograms => hw4programs}/run3.oat | 0 hw5/{oatprograms => hw4programs}/run30.oat | 0 hw5/{oatprograms => hw4programs}/run31.oat | 0 hw5/{oatprograms => hw4programs}/run32.oat | 0 hw5/{oatprograms => hw4programs}/run33.oat | 0 hw5/{oatprograms => hw4programs}/run34.oat | 0 hw5/{oatprograms => hw4programs}/run35.oat | 0 hw5/{oatprograms => hw4programs}/run36.oat | 0 hw5/{oatprograms => hw4programs}/run37.oat | 0 hw5/{oatprograms => hw4programs}/run38.oat | 0 hw5/{oatprograms => hw4programs}/run39.oat | 0 hw5/{oatprograms => hw4programs}/run4.oat | 0 hw5/{oatprograms => hw4programs}/run40.oat | 0 hw5/{oatprograms => hw4programs}/run41.oat | 0 hw5/hw4programs/run42.oat | 16 + hw5/{oatprograms => hw4programs}/run43.oat | 0 hw5/hw4programs/run44.oat | 19 + hw5/{oatprograms => hw4programs}/run45.oat | 0 hw5/{oatprograms => hw4programs}/run46.oat | 0 hw5/{oatprograms => hw4programs}/run47.oat | 4 +- hw5/{oatprograms => hw4programs}/run48.oat | 4 +- hw5/{oatprograms => hw4programs}/run49.oat | 0 hw5/{oatprograms => hw4programs}/run5.oat | 0 hw5/{oatprograms => hw4programs}/run50.oat | 0 hw5/{oatprograms => hw4programs}/run51.oat | 0 hw5/{oatprograms => hw4programs}/run52.oat | 0 hw5/{oatprograms => hw4programs}/run53.oat | 0 hw5/{oatprograms => hw4programs}/run54.oat | 0 hw5/{oatprograms => hw4programs}/run55.oat | 0 hw5/{oatprograms => hw4programs}/run56.oat | 0 hw5/{oatprograms => hw4programs}/run6.oat | 0 hw5/{oatprograms => hw4programs}/run60.oat | 0 hw5/{oatprograms => hw4programs}/run61.oat | 0 hw5/{oatprograms => hw4programs}/run7.oat | 0 hw5/{oatprograms => hw4programs}/run8.oat | 0 hw5/{oatprograms => hw4programs}/run9.oat | 0 .../runtime-fail1.oat | 0 .../runtime-fail2.oat | 0 .../runtime-fail3.oat | 0 .../runtime-fail4.oat | 0 .../selectionsort.oat | 0 hw5/hw4programs/setg.oat | 15 + .../shortest_path_matrix.oat | 0 hw5/{oatprograms => hw4programs}/sieve.oat | 2 +- hw5/{oatprograms => hw4programs}/sqrt.oat | 0 hw5/{oatprograms => hw4programs}/tc1.oat | 0 hw5/{oatprograms => hw4programs}/tc10.oat | 0 hw5/{oatprograms => hw4programs}/tc11.oat | 0 hw5/{oatprograms => hw4programs}/tc12.oat | 0 hw5/{oatprograms => hw4programs}/tc13.oat | 0 hw5/{oatprograms => hw4programs}/tc14.oat | 0 hw5/{oatprograms => hw4programs}/tc15.oat | 0 hw5/{oatprograms => hw4programs}/tc16.oat | 0 hw5/{oatprograms => hw4programs}/tc17.oat | 0 hw5/{oatprograms => hw4programs}/tc18.oat | 0 hw5/{oatprograms => hw4programs}/tc19.oat | 0 hw5/{oatprograms => hw4programs}/tc2.oat | 0 hw5/{oatprograms => hw4programs}/tc20.oat | 0 hw5/{oatprograms => hw4programs}/tc3.oat | 0 hw5/{oatprograms => hw4programs}/tc4.oat | 0 hw5/{oatprograms => hw4programs}/tc5.oat | 0 hw5/{oatprograms => hw4programs}/tc6.oat | 0 hw5/{oatprograms => hw4programs}/tc7.oat | 0 hw5/{oatprograms => hw4programs}/tc8.oat | 0 hw5/{oatprograms => hw4programs}/tc9.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok1.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok2.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok4.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok5.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok6.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok7.oat | 0 hw5/{oatprograms => hw4programs}/tc_ok8.oat | 0 hw5/{oatprograms => hw4programs}/toascii.oat | 0 hw5/{oatprograms => hw4programs}/toposort.oat | 0 .../union_find.oat | 0 hw5/{oatprograms => hw4programs}/xor_bool.oat | 0 .../xor_shift.oat | 2 +- hw5/{team.txt => hw5.opam} | 0 hw5/hw5programs/apoth_composition.oat | 2 +- hw5/hw5programs/array_oob.oat | 8 + hw5/hw5programs/burowski_bfs.oat | 2 +- hw5/hw5programs/compile_array_init.oat | 7 + hw5/{oatprograms => hw5programs}/conquest.oat | 21 +- hw5/hw5programs/field_overlap.oat | 13 + hw5/hw5programs/for_scope.oat | 8 + hw5/hw5programs/gregor.oat | 5 - hw5/hw5programs/ifq1.oat | 11 + hw5/hw5programs/ifq2.oat | 10 + hw5/hw5programs/ifq3.oat | 16 + hw5/hw5programs/ifq4.oat | 16 + hw5/hw5programs/ifq5.oat | 17 + hw5/hw5programs/leqiliu_traversal.oat | 120 ++--- hw5/hw5programs/maale_odd_even.oat | 68 +-- hw5/hw5programs/myprogram.oat | 12 - hw5/hw5programs/poem.oat | 52 ++ .../run44.oat => hw5programs/run44fixed.oat} | 4 +- hw5/hw5programs/tc_correct_array2.oat | 4 + hw5/hw5programs/tc_correct_array3.oat | 4 + ...e.oat => tc_correct_global_fptr_scope.oat} | 0 hw5/hw5programs/tc_eq1.oat | 14 + hw5/hw5programs/tc_eq2.oat | 14 + hw5/hw5programs/tc_error_array3.oat | 4 + hw5/hw5programs/tc_error_array4.oat | 4 + hw5/hw5programs/tc_struct_null_field.oat | 18 + hw5/hw5programs/tc_subtyping7.oat | 2 +- hw5/hw5programs/tc_subtyping8.oat | 2 +- hw5/hw5programs/tc_subtyping9.oat | 2 +- hw5/lib/ll/dune | 7 + hw5/lib/ll/ll-original.ml | 81 +++ hw5/{ => lib}/ll/ll.ml | 6 +- hw5/lib/ll/llinterp.ml | 478 +++++++++++++++++ hw5/{ => lib}/ll/lllexer.mll | 9 +- hw5/{ => lib}/ll/llparser.mly | 11 +- hw5/{ => lib}/ll/llruntime.c | 0 hw5/{ => lib}/ll/llutil.ml | 58 ++- hw5/lib/util/assert.ml | 195 +++++++ hw5/{ => lib}/util/assert.mli | 28 +- hw5/lib/util/dune | 3 + hw5/lib/util/platform.ml | 237 +++++++++ hw5/lib/util/range.ml | 56 ++ hw5/{ => lib}/util/range.mli | 4 +- hw5/lib/x86/dune | 3 + hw5/{ => lib}/x86/x86.ml | 10 +- hw5/oatprograms/bubble_sort.oat | 30 -- hw5/oatprograms/determinant_size2.oat | 31 -- hw5/oatprograms/easy_p5.oat | 14 - hw5/oatprograms/run15.oat | 15 - hw5/oatprograms/run16.oat | 6 - hw5/oatprograms/run17.oat | 12 - hw5/oatprograms/run42.oat | 16 - hw5/studenttests.ml | 10 - hw5/submit_zip_contents.txt | 3 + hw5/test/dune | 22 + hw5/test/gradedtests.ml | 404 +++++++++++++++ hw5/test/studenttests.ml | 18 + hw5/test/testlib.ml | 157 ++++++ hw5/util/assert.ml | 160 ------ hw5/util/platform.ml | 156 ------ hw5/util/range.ml | 41 -- hw5/x86/testX86.ml | 34 -- 262 files changed, 2575 insertions(+), 1442 deletions(-) create mode 100644 hw5/.ocamlformat create mode 100644 hw5/.ocamlinit delete mode 100644 hw5/README create mode 100644 hw5/README.md rename hw5/{ => bin}/ast.ml (94%) rename hw5/{ => bin}/astlib.ml (97%) rename hw5/{ => bin}/backend.ml (99%) rename hw5/{ => bin}/driver.ml (97%) create mode 100644 hw5/bin/dune rename hw5/{ => bin}/frontend.ml (87%) rename hw5/{ => bin}/lexer.mll (99%) rename hw5/{ => bin}/main.ml (82%) rename hw5/{ => bin}/parser.mly (96%) rename hw5/{ => bin}/runtime.c (96%) rename hw5/{ => bin}/tctxt.ml (100%) rename hw5/{ => bin}/typechecker.ml (88%) create mode 100644 hw5/dune-project delete mode 100644 hw5/gradedtests.ml create mode 100644 hw5/hw4programs/abs.oat create mode 100644 hw5/hw4programs/argassign.oat rename hw5/{oatprograms => hw4programs}/arrayargs.oat (100%) rename hw5/{oatprograms => hw4programs}/arrayargs1.oat (100%) rename hw5/{oatprograms => hw4programs}/arrayargs2.oat (74%) rename hw5/{oatprograms => hw4programs}/arrayargs3.oat (100%) rename hw5/{oatprograms => hw4programs}/arrayargs4.oat (100%) rename hw5/{oatprograms => hw4programs}/binary_gcd.oat (100%) rename hw5/{oatprograms => hw4programs}/binary_search.oat (96%) rename hw5/{oatprograms => hw4programs}/bsort.oat (95%) rename hw5/{oatprograms => hw4programs}/calculator.oat (100%) rename hw5/{oatprograms => hw4programs}/count_sort.oat (92%) rename hw5/{oatprograms => hw4programs}/easy_p1.oat (100%) rename hw5/{oatprograms => hw4programs}/easy_p2.oat (100%) rename hw5/{oatprograms => hw4programs}/easy_p3.oat (100%) rename hw5/{oatprograms => hw4programs}/easy_p4.oat (100%) create mode 100644 hw5/hw4programs/easy_p5.oat rename hw5/{oatprograms => hw4programs}/easy_p6.oat (100%) rename hw5/{oatprograms => hw4programs}/easy_p7.oat (67%) rename hw5/{oatprograms => hw4programs}/easyrun1.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun10.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun2.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun3.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun4.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun5.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun6.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun7.oat (100%) rename hw5/{oatprograms => hw4programs}/easyrun8.oat (64%) rename hw5/{oatprograms => hw4programs}/easyrun9.oat (100%) rename hw5/{oatprograms => hw4programs}/fac.oat (100%) rename hw5/{oatprograms => hw4programs}/fact.oat (100%) rename hw5/{oatprograms => hw4programs}/fibo.oat (100%) rename hw5/{oatprograms => hw4programs}/float_multiply.oat (95%) rename hw5/{oatprograms => hw4programs}/gcd.oat (100%) rename hw5/{oatprograms => hw4programs}/globals1.oat (100%) rename hw5/{oatprograms => hw4programs}/globals2.oat (100%) rename hw5/{oatprograms => hw4programs}/globals3.oat (100%) rename hw5/{oatprograms => hw4programs}/globals4.oat (100%) rename hw5/{oatprograms => hw4programs}/globals5.oat (100%) rename hw5/{oatprograms => hw4programs}/globals6.oat (100%) create mode 100644 hw5/hw4programs/globals7.oat rename hw5/{oatprograms => hw4programs}/gnomesort.oat (100%) rename hw5/{oatprograms => hw4programs}/hashcode.oat (100%) rename hw5/{oatprograms => hw4programs}/heap.oat (100%) rename hw5/{oatprograms => hw4programs}/insertion_sort.oat (95%) rename hw5/{oatprograms => hw4programs}/is_prime.oat (100%) rename hw5/{oatprograms => hw4programs}/josh_joyce_test.oat (100%) rename hw5/{oatprograms => hw4programs}/kmp.oat (100%) rename hw5/{oatprograms => hw4programs}/lcs.oat (100%) rename hw5/{oatprograms => hw4programs}/leastsquare.oat (100%) rename hw5/{oatprograms => hw4programs}/lfsr.oat (95%) rename hw5/{oatprograms => hw4programs}/lfsr2.oat (100%) rename hw5/{oatprograms => hw4programs}/lib10.oat (100%) rename hw5/{oatprograms => hw4programs}/lib11.oat (100%) rename hw5/{oatprograms => hw4programs}/lib12.oat (100%) rename hw5/{oatprograms => hw4programs}/lib13.oat (100%) rename hw5/{oatprograms => hw4programs}/lib14.oat (100%) rename hw5/{oatprograms => hw4programs}/lib15.oat (68%) rename hw5/{oatprograms => hw4programs}/lib2.oat (100%) rename hw5/{oatprograms => hw4programs}/lib3.oat (100%) rename hw5/{oatprograms => hw4programs}/lib4.oat (100%) rename hw5/{oatprograms => hw4programs}/lib5.oat (100%) rename hw5/{oatprograms => hw4programs}/lib6.oat (100%) rename hw5/{oatprograms => hw4programs}/lib7.oat (100%) rename hw5/{oatprograms => hw4programs}/lib8.oat (100%) rename hw5/{oatprograms => hw4programs}/lib9.oat (100%) rename hw5/{oatprograms => hw4programs}/life.oat (86%) rename hw5/{oatprograms => hw4programs}/matrixmult.oat (100%) rename hw5/{oatprograms => hw4programs}/maxsubsequence.oat (93%) rename hw5/{oatprograms => hw4programs}/msort.oat (97%) rename hw5/{oatprograms => hw4programs}/msort2.oat (97%) rename hw5/{oatprograms => hw4programs}/no_of_fac.oat (94%) rename hw5/{oatprograms => hw4programs}/path1.oat (100%) rename hw5/{oatprograms => hw4programs}/path2.oat (100%) rename hw5/{oatprograms => hw4programs}/path3.oat (100%) rename hw5/{oatprograms => hw4programs}/phase2_1.oat (100%) rename hw5/{oatprograms => hw4programs}/qs_bs.oat (100%) rename hw5/{oatprograms => hw4programs}/qsort.oat (100%) rename hw5/{oatprograms => hw4programs}/regalloctest.oat (100%) rename hw5/{oatprograms => hw4programs}/regalloctest2.oat (100%) rename hw5/{oatprograms => hw4programs}/regex.oat (100%) rename hw5/{oatprograms => hw4programs}/reverse.oat (100%) rename hw5/{oatprograms => hw4programs}/rod_cutting.oat (100%) rename hw5/{oatprograms => hw4programs}/run1.oat (100%) rename hw5/{oatprograms => hw4programs}/run10.oat (100%) rename hw5/{oatprograms => hw4programs}/run11.oat (100%) rename hw5/{oatprograms => hw4programs}/run13.oat (100%) rename hw5/{oatprograms => hw4programs}/run14.oat (74%) create mode 100644 hw5/hw4programs/run15.oat create mode 100644 hw5/hw4programs/run16.oat rename hw5/{oatprograms => hw4programs}/run18.oat (100%) rename hw5/{oatprograms => hw4programs}/run19.oat (100%) rename hw5/{oatprograms => hw4programs}/run2.oat (100%) rename hw5/{oatprograms => hw4programs}/run20.oat (100%) rename hw5/{oatprograms => hw4programs}/run21.oat (100%) rename hw5/{oatprograms => hw4programs}/run22.oat (100%) rename hw5/{oatprograms => hw4programs}/run23.oat (100%) rename hw5/{oatprograms => hw4programs}/run24.oat (100%) rename hw5/{oatprograms => hw4programs}/run25.oat (75%) rename hw5/{oatprograms => hw4programs}/run26.oat (100%) rename hw5/{oatprograms => hw4programs}/run27.oat (100%) rename hw5/{oatprograms => hw4programs}/run28.oat (100%) rename hw5/{oatprograms => hw4programs}/run29.oat (100%) rename hw5/{oatprograms => hw4programs}/run3.oat (100%) rename hw5/{oatprograms => hw4programs}/run30.oat (100%) rename hw5/{oatprograms => hw4programs}/run31.oat (100%) rename hw5/{oatprograms => hw4programs}/run32.oat (100%) rename hw5/{oatprograms => hw4programs}/run33.oat (100%) rename hw5/{oatprograms => hw4programs}/run34.oat (100%) rename hw5/{oatprograms => hw4programs}/run35.oat (100%) rename hw5/{oatprograms => hw4programs}/run36.oat (100%) rename hw5/{oatprograms => hw4programs}/run37.oat (100%) rename hw5/{oatprograms => hw4programs}/run38.oat (100%) rename hw5/{oatprograms => hw4programs}/run39.oat (100%) rename hw5/{oatprograms => hw4programs}/run4.oat (100%) rename hw5/{oatprograms => hw4programs}/run40.oat (100%) rename hw5/{oatprograms => hw4programs}/run41.oat (100%) create mode 100644 hw5/hw4programs/run42.oat rename hw5/{oatprograms => hw4programs}/run43.oat (100%) create mode 100644 hw5/hw4programs/run44.oat rename hw5/{oatprograms => hw4programs}/run45.oat (100%) rename hw5/{oatprograms => hw4programs}/run46.oat (100%) rename hw5/{oatprograms => hw4programs}/run47.oat (71%) rename hw5/{oatprograms => hw4programs}/run48.oat (70%) rename hw5/{oatprograms => hw4programs}/run49.oat (100%) rename hw5/{oatprograms => hw4programs}/run5.oat (100%) rename hw5/{oatprograms => hw4programs}/run50.oat (100%) rename hw5/{oatprograms => hw4programs}/run51.oat (100%) rename hw5/{oatprograms => hw4programs}/run52.oat (100%) rename hw5/{oatprograms => hw4programs}/run53.oat (100%) rename hw5/{oatprograms => hw4programs}/run54.oat (100%) rename hw5/{oatprograms => hw4programs}/run55.oat (100%) rename hw5/{oatprograms => hw4programs}/run56.oat (100%) rename hw5/{oatprograms => hw4programs}/run6.oat (100%) rename hw5/{oatprograms => hw4programs}/run60.oat (100%) rename hw5/{oatprograms => hw4programs}/run61.oat (100%) rename hw5/{oatprograms => hw4programs}/run7.oat (100%) rename hw5/{oatprograms => hw4programs}/run8.oat (100%) rename hw5/{oatprograms => hw4programs}/run9.oat (100%) rename hw5/{oatprograms => hw4programs}/runtime-fail1.oat (100%) rename hw5/{oatprograms => hw4programs}/runtime-fail2.oat (100%) rename hw5/{oatprograms => hw4programs}/runtime-fail3.oat (100%) rename hw5/{oatprograms => hw4programs}/runtime-fail4.oat (100%) rename hw5/{oatprograms => hw4programs}/selectionsort.oat (100%) create mode 100644 hw5/hw4programs/setg.oat rename hw5/{oatprograms => hw4programs}/shortest_path_matrix.oat (100%) rename hw5/{oatprograms => hw4programs}/sieve.oat (92%) rename hw5/{oatprograms => hw4programs}/sqrt.oat (100%) rename hw5/{oatprograms => hw4programs}/tc1.oat (100%) rename hw5/{oatprograms => hw4programs}/tc10.oat (100%) rename hw5/{oatprograms => hw4programs}/tc11.oat (100%) rename hw5/{oatprograms => hw4programs}/tc12.oat (100%) rename hw5/{oatprograms => hw4programs}/tc13.oat (100%) rename hw5/{oatprograms => hw4programs}/tc14.oat (100%) rename hw5/{oatprograms => hw4programs}/tc15.oat (100%) rename hw5/{oatprograms => hw4programs}/tc16.oat (100%) rename hw5/{oatprograms => hw4programs}/tc17.oat (100%) rename hw5/{oatprograms => hw4programs}/tc18.oat (100%) rename hw5/{oatprograms => hw4programs}/tc19.oat (100%) rename hw5/{oatprograms => hw4programs}/tc2.oat (100%) rename hw5/{oatprograms => hw4programs}/tc20.oat (100%) rename hw5/{oatprograms => hw4programs}/tc3.oat (100%) rename hw5/{oatprograms => hw4programs}/tc4.oat (100%) rename hw5/{oatprograms => hw4programs}/tc5.oat (100%) rename hw5/{oatprograms => hw4programs}/tc6.oat (100%) rename hw5/{oatprograms => hw4programs}/tc7.oat (100%) rename hw5/{oatprograms => hw4programs}/tc8.oat (100%) rename hw5/{oatprograms => hw4programs}/tc9.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok1.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok2.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok4.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok5.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok6.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok7.oat (100%) rename hw5/{oatprograms => hw4programs}/tc_ok8.oat (100%) rename hw5/{oatprograms => hw4programs}/toascii.oat (100%) rename hw5/{oatprograms => hw4programs}/toposort.oat (100%) rename hw5/{oatprograms => hw4programs}/union_find.oat (100%) rename hw5/{oatprograms => hw4programs}/xor_bool.oat (100%) rename hw5/{oatprograms => hw4programs}/xor_shift.oat (93%) rename hw5/{team.txt => hw5.opam} (100%) create mode 100644 hw5/hw5programs/array_oob.oat create mode 100644 hw5/hw5programs/compile_array_init.oat rename hw5/{oatprograms => hw5programs}/conquest.oat (88%) create mode 100644 hw5/hw5programs/field_overlap.oat create mode 100644 hw5/hw5programs/for_scope.oat delete mode 100644 hw5/hw5programs/gregor.oat create mode 100644 hw5/hw5programs/ifq1.oat create mode 100644 hw5/hw5programs/ifq2.oat create mode 100644 hw5/hw5programs/ifq3.oat create mode 100644 hw5/hw5programs/ifq4.oat create mode 100644 hw5/hw5programs/ifq5.oat delete mode 100644 hw5/hw5programs/myprogram.oat create mode 100644 hw5/hw5programs/poem.oat rename hw5/{oatprograms/run44.oat => hw5programs/run44fixed.oat} (81%) create mode 100644 hw5/hw5programs/tc_correct_array2.oat create mode 100644 hw5/hw5programs/tc_correct_array3.oat rename hw5/hw5programs/{tc_error_global_fptr_scope.oat => tc_correct_global_fptr_scope.oat} (100%) create mode 100644 hw5/hw5programs/tc_eq1.oat create mode 100644 hw5/hw5programs/tc_eq2.oat create mode 100644 hw5/hw5programs/tc_error_array3.oat create mode 100644 hw5/hw5programs/tc_error_array4.oat create mode 100644 hw5/hw5programs/tc_struct_null_field.oat create mode 100644 hw5/lib/ll/dune create mode 100644 hw5/lib/ll/ll-original.ml rename hw5/{ => lib}/ll/ll.ml (90%) create mode 100644 hw5/lib/ll/llinterp.ml rename hw5/{ => lib}/ll/lllexer.mll (91%) rename hw5/{ => lib}/ll/llparser.mly (96%) rename hw5/{ => lib}/ll/llruntime.c (100%) rename hw5/{ => lib}/ll/llutil.ml (74%) create mode 100644 hw5/lib/util/assert.ml rename hw5/{ => lib}/util/assert.mli (77%) create mode 100644 hw5/lib/util/dune create mode 100644 hw5/lib/util/platform.ml create mode 100644 hw5/lib/util/range.ml rename hw5/{ => lib}/util/range.mli (92%) create mode 100644 hw5/lib/x86/dune rename hw5/{ => lib}/x86/x86.ml (95%) delete mode 100644 hw5/oatprograms/bubble_sort.oat delete mode 100644 hw5/oatprograms/determinant_size2.oat delete mode 100644 hw5/oatprograms/easy_p5.oat delete mode 100644 hw5/oatprograms/run15.oat delete mode 100644 hw5/oatprograms/run16.oat delete mode 100644 hw5/oatprograms/run17.oat delete mode 100644 hw5/oatprograms/run42.oat delete mode 100644 hw5/studenttests.ml create mode 100644 hw5/submit_zip_contents.txt create mode 100644 hw5/test/dune create mode 100644 hw5/test/gradedtests.ml create mode 100644 hw5/test/studenttests.ml create mode 100644 hw5/test/testlib.ml delete mode 100644 hw5/util/assert.ml delete mode 100644 hw5/util/platform.ml delete mode 100644 hw5/util/range.ml delete mode 100644 hw5/x86/testX86.ml diff --git a/hw5/.ocamlformat b/hw5/.ocamlformat new file mode 100644 index 0000000..fd111e4 --- /dev/null +++ b/hw5/.ocamlformat @@ -0,0 +1,2 @@ +profile = janestreet +version = 0.26.1 diff --git a/hw5/.ocamlinit b/hw5/.ocamlinit new file mode 100644 index 0000000..576e012 --- /dev/null +++ b/hw5/.ocamlinit @@ -0,0 +1 @@ +#use_output "dune top";; diff --git a/hw5/Makefile b/hw5/Makefile index b15400c..4fe6cfd 100644 --- a/hw5/Makefile +++ b/hw5/Makefile @@ -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 +# diff --git a/hw5/README b/hw5/README deleted file mode 100644 index dbaa201..0000000 --- a/hw5/README +++ /dev/null @@ -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 - 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 diff --git a/hw5/README.md b/hw5/README.md new file mode 100644 index 0000000..9d46692 --- /dev/null +++ b/hw5/README.md @@ -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 ```` | 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 diff --git a/hw5/ast.ml b/hw5/bin/ast.ml similarity index 94% rename from hw5/ast.ml rename to hw5/bin/ast.ml index 69a3400..ee30e22 100644 --- a/hw5/ast.ml +++ b/hw5/bin/ast.ml @@ -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 diff --git a/hw5/astlib.ml b/hw5/bin/astlib.ml similarity index 97% rename from hw5/astlib.ml rename to hw5/bin/astlib.ml index 6bba09e..2a61610 100644 --- a/hw5/astlib.ml +++ b/hw5/bin/astlib.ml @@ -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)" diff --git a/hw5/backend.ml b/hw5/bin/backend.ml similarity index 99% rename from hw5/backend.ml rename to hw5/bin/backend.ml index beebfd6..278d96c 100644 --- a/hw5/backend.ml +++ b/hw5/bin/backend.ml @@ -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 diff --git a/hw5/driver.ml b/hw5/bin/driver.ml similarity index 97% rename from hw5/driver.ml rename to hw5/bin/driver.ml index dbcc82a..2d91e91 100644 --- a/hw5/driver.ml +++ b/hw5/bin/driver.ml @@ -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; diff --git a/hw5/bin/dune b/hw5/bin/dune new file mode 100644 index 0000000..0672023 --- /dev/null +++ b/hw5/bin/dune @@ -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)) diff --git a/hw5/frontend.ml b/hw5/bin/frontend.ml similarity index 87% rename from hw5/frontend.ml rename to hw5/bin/frontend.ml index 4c537f1..337d1c2 100644 --- a/hw5/frontend.ml +++ b/hw5/bin/frontend.ml @@ -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) -> diff --git a/hw5/lexer.mll b/hw5/bin/lexer.mll similarity index 99% rename from hw5/lexer.mll rename to hw5/bin/lexer.mll index 252617e..0ed0803 100644 --- a/hw5/lexer.mll +++ b/hw5/bin/lexer.mll @@ -1,6 +1,8 @@ { open Lexing open Parser + + module Range = Util.Range open Range exception Lexer_error of Range.t * string diff --git a/hw5/main.ml b/hw5/bin/main.ml similarity index 82% rename from hw5/main.ml rename to hw5/bin/main.ml index 70daaa6..9fa92b7 100644 --- a/hw5/main.ml +++ b/hw5/bin/main.ml @@ -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] \n\ see README for details about using the compiler"; Platform.configure_os (); diff --git a/hw5/parser.mly b/hw5/bin/parser.mly similarity index 96% rename from hw5/parser.mly rename to hw5/bin/parser.mly index 2036fc7..4fc45dd 100644 --- a/hw5/parser.mly +++ b/hw5/bin/parser.mly @@ -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) } diff --git a/hw5/runtime.c b/hw5/bin/runtime.c similarity index 96% rename from hw5/runtime.c rename to hw5/bin/runtime.c index d1b32af..9aba2fe 100644 --- a/hw5/runtime.c +++ b/hw5/bin/runtime.c @@ -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 diff --git a/hw5/tctxt.ml b/hw5/bin/tctxt.ml similarity index 100% rename from hw5/tctxt.ml rename to hw5/bin/tctxt.ml diff --git a/hw5/typechecker.ml b/hw5/bin/typechecker.ml similarity index 88% rename from hw5/typechecker.ml rename to hw5/bin/typechecker.ml index d18718f..4d7ed4c 100644 --- a/hw5/typechecker.ml +++ b/hw5/bin/typechecker.ml @@ -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" diff --git a/hw5/dune-project b/hw5/dune-project new file mode 100644 index 0000000..9708423 --- /dev/null +++ b/hw5/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.9) +(name hw5) +(using menhir 2.1) diff --git a/hw5/gradedtests.ml b/hw5/gradedtests.ml deleted file mode 100644 index d39a649..0000000 --- a/hw5/gradedtests.ml +++ /dev/null @@ -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 diff --git a/hw5/hw4programs/abs.oat b/hw5/hw4programs/abs.oat new file mode 100644 index 0000000..4f9df75 --- /dev/null +++ b/hw5/hw4programs/abs.oat @@ -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; +} diff --git a/hw5/hw4programs/argassign.oat b/hw5/hw4programs/argassign.oat new file mode 100644 index 0000000..446c90c --- /dev/null +++ b/hw5/hw4programs/argassign.oat @@ -0,0 +1,8 @@ +int foo(int x) { + x = x + 1; + return x; +} + +int program (int argc, string[] argv) { + return foo(17); +} diff --git a/hw5/oatprograms/arrayargs.oat b/hw5/hw4programs/arrayargs.oat similarity index 100% rename from hw5/oatprograms/arrayargs.oat rename to hw5/hw4programs/arrayargs.oat diff --git a/hw5/oatprograms/arrayargs1.oat b/hw5/hw4programs/arrayargs1.oat similarity index 100% rename from hw5/oatprograms/arrayargs1.oat rename to hw5/hw4programs/arrayargs1.oat diff --git a/hw5/oatprograms/arrayargs2.oat b/hw5/hw4programs/arrayargs2.oat similarity index 74% rename from hw5/oatprograms/arrayargs2.oat rename to hw5/hw4programs/arrayargs2.oat index 64c93f6..1e31732 100644 --- a/hw5/oatprograms/arrayargs2.oat +++ b/hw5/hw4programs/arrayargs2.oat @@ -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]; } diff --git a/hw5/oatprograms/arrayargs3.oat b/hw5/hw4programs/arrayargs3.oat similarity index 100% rename from hw5/oatprograms/arrayargs3.oat rename to hw5/hw4programs/arrayargs3.oat diff --git a/hw5/oatprograms/arrayargs4.oat b/hw5/hw4programs/arrayargs4.oat similarity index 100% rename from hw5/oatprograms/arrayargs4.oat rename to hw5/hw4programs/arrayargs4.oat diff --git a/hw5/oatprograms/binary_gcd.oat b/hw5/hw4programs/binary_gcd.oat similarity index 100% rename from hw5/oatprograms/binary_gcd.oat rename to hw5/hw4programs/binary_gcd.oat diff --git a/hw5/oatprograms/binary_search.oat b/hw5/hw4programs/binary_search.oat similarity index 96% rename from hw5/oatprograms/binary_search.oat rename to hw5/hw4programs/binary_search.oat index 7ab66db..192c264 100644 --- a/hw5/oatprograms/binary_search.oat +++ b/hw5/hw4programs/binary_search.oat @@ -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); diff --git a/hw5/oatprograms/bsort.oat b/hw5/hw4programs/bsort.oat similarity index 95% rename from hw5/oatprograms/bsort.oat rename to hw5/hw4programs/bsort.oat index 2123e08..a4544c9 100644 --- a/hw5/oatprograms/bsort.oat +++ b/hw5/hw4programs/bsort.oat @@ -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; diff --git a/hw5/oatprograms/calculator.oat b/hw5/hw4programs/calculator.oat similarity index 100% rename from hw5/oatprograms/calculator.oat rename to hw5/hw4programs/calculator.oat diff --git a/hw5/oatprograms/count_sort.oat b/hw5/hw4programs/count_sort.oat similarity index 92% rename from hw5/oatprograms/count_sort.oat rename to hw5/hw4programs/count_sort.oat index e900df9..1197eb8 100644 --- a/hw5/oatprograms/count_sort.oat +++ b/hw5/hw4programs/count_sort.oat @@ -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) { diff --git a/hw5/oatprograms/easy_p1.oat b/hw5/hw4programs/easy_p1.oat similarity index 100% rename from hw5/oatprograms/easy_p1.oat rename to hw5/hw4programs/easy_p1.oat diff --git a/hw5/oatprograms/easy_p2.oat b/hw5/hw4programs/easy_p2.oat similarity index 100% rename from hw5/oatprograms/easy_p2.oat rename to hw5/hw4programs/easy_p2.oat diff --git a/hw5/oatprograms/easy_p3.oat b/hw5/hw4programs/easy_p3.oat similarity index 100% rename from hw5/oatprograms/easy_p3.oat rename to hw5/hw4programs/easy_p3.oat diff --git a/hw5/oatprograms/easy_p4.oat b/hw5/hw4programs/easy_p4.oat similarity index 100% rename from hw5/oatprograms/easy_p4.oat rename to hw5/hw4programs/easy_p4.oat diff --git a/hw5/hw4programs/easy_p5.oat b/hw5/hw4programs/easy_p5.oat new file mode 100644 index 0000000..a9231fc --- /dev/null +++ b/hw5/hw4programs/easy_p5.oat @@ -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"} + }; diff --git a/hw5/oatprograms/easy_p6.oat b/hw5/hw4programs/easy_p6.oat similarity index 100% rename from hw5/oatprograms/easy_p6.oat rename to hw5/hw4programs/easy_p6.oat diff --git a/hw5/oatprograms/easy_p7.oat b/hw5/hw4programs/easy_p7.oat similarity index 67% rename from hw5/oatprograms/easy_p7.oat rename to hw5/hw4programs/easy_p7.oat index ed330b1..bc0f929 100644 --- a/hw5/oatprograms/easy_p7.oat +++ b/hw5/hw4programs/easy_p7.oat @@ -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]; } diff --git a/hw5/oatprograms/easyrun1.oat b/hw5/hw4programs/easyrun1.oat similarity index 100% rename from hw5/oatprograms/easyrun1.oat rename to hw5/hw4programs/easyrun1.oat diff --git a/hw5/oatprograms/easyrun10.oat b/hw5/hw4programs/easyrun10.oat similarity index 100% rename from hw5/oatprograms/easyrun10.oat rename to hw5/hw4programs/easyrun10.oat diff --git a/hw5/oatprograms/easyrun2.oat b/hw5/hw4programs/easyrun2.oat similarity index 100% rename from hw5/oatprograms/easyrun2.oat rename to hw5/hw4programs/easyrun2.oat diff --git a/hw5/oatprograms/easyrun3.oat b/hw5/hw4programs/easyrun3.oat similarity index 100% rename from hw5/oatprograms/easyrun3.oat rename to hw5/hw4programs/easyrun3.oat diff --git a/hw5/oatprograms/easyrun4.oat b/hw5/hw4programs/easyrun4.oat similarity index 100% rename from hw5/oatprograms/easyrun4.oat rename to hw5/hw4programs/easyrun4.oat diff --git a/hw5/oatprograms/easyrun5.oat b/hw5/hw4programs/easyrun5.oat similarity index 100% rename from hw5/oatprograms/easyrun5.oat rename to hw5/hw4programs/easyrun5.oat diff --git a/hw5/oatprograms/easyrun6.oat b/hw5/hw4programs/easyrun6.oat similarity index 100% rename from hw5/oatprograms/easyrun6.oat rename to hw5/hw4programs/easyrun6.oat diff --git a/hw5/oatprograms/easyrun7.oat b/hw5/hw4programs/easyrun7.oat similarity index 100% rename from hw5/oatprograms/easyrun7.oat rename to hw5/hw4programs/easyrun7.oat diff --git a/hw5/oatprograms/easyrun8.oat b/hw5/hw4programs/easyrun8.oat similarity index 64% rename from hw5/oatprograms/easyrun8.oat rename to hw5/hw4programs/easyrun8.oat index 21cbce6..a5607fd 100644 --- a/hw5/oatprograms/easyrun8.oat +++ b/hw5/hw4programs/easyrun8.oat @@ -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; } diff --git a/hw5/oatprograms/easyrun9.oat b/hw5/hw4programs/easyrun9.oat similarity index 100% rename from hw5/oatprograms/easyrun9.oat rename to hw5/hw4programs/easyrun9.oat diff --git a/hw5/oatprograms/fac.oat b/hw5/hw4programs/fac.oat similarity index 100% rename from hw5/oatprograms/fac.oat rename to hw5/hw4programs/fac.oat diff --git a/hw5/oatprograms/fact.oat b/hw5/hw4programs/fact.oat similarity index 100% rename from hw5/oatprograms/fact.oat rename to hw5/hw4programs/fact.oat diff --git a/hw5/oatprograms/fibo.oat b/hw5/hw4programs/fibo.oat similarity index 100% rename from hw5/oatprograms/fibo.oat rename to hw5/hw4programs/fibo.oat diff --git a/hw5/oatprograms/float_multiply.oat b/hw5/hw4programs/float_multiply.oat similarity index 95% rename from hw5/oatprograms/float_multiply.oat rename to hw5/hw4programs/float_multiply.oat index cdb2b00..2548138 100644 --- a/hw5/oatprograms/float_multiply.oat +++ b/hw5/hw4programs/float_multiply.oat @@ -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; } \ No newline at end of file diff --git a/hw5/oatprograms/gcd.oat b/hw5/hw4programs/gcd.oat similarity index 100% rename from hw5/oatprograms/gcd.oat rename to hw5/hw4programs/gcd.oat diff --git a/hw5/oatprograms/globals1.oat b/hw5/hw4programs/globals1.oat similarity index 100% rename from hw5/oatprograms/globals1.oat rename to hw5/hw4programs/globals1.oat diff --git a/hw5/oatprograms/globals2.oat b/hw5/hw4programs/globals2.oat similarity index 100% rename from hw5/oatprograms/globals2.oat rename to hw5/hw4programs/globals2.oat diff --git a/hw5/oatprograms/globals3.oat b/hw5/hw4programs/globals3.oat similarity index 100% rename from hw5/oatprograms/globals3.oat rename to hw5/hw4programs/globals3.oat diff --git a/hw5/oatprograms/globals4.oat b/hw5/hw4programs/globals4.oat similarity index 100% rename from hw5/oatprograms/globals4.oat rename to hw5/hw4programs/globals4.oat diff --git a/hw5/oatprograms/globals5.oat b/hw5/hw4programs/globals5.oat similarity index 100% rename from hw5/oatprograms/globals5.oat rename to hw5/hw4programs/globals5.oat diff --git a/hw5/oatprograms/globals6.oat b/hw5/hw4programs/globals6.oat similarity index 100% rename from hw5/oatprograms/globals6.oat rename to hw5/hw4programs/globals6.oat diff --git a/hw5/hw4programs/globals7.oat b/hw5/hw4programs/globals7.oat new file mode 100644 index 0000000..7645ed2 --- /dev/null +++ b/hw5/hw4programs/globals7.oat @@ -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]; +} \ No newline at end of file diff --git a/hw5/oatprograms/gnomesort.oat b/hw5/hw4programs/gnomesort.oat similarity index 100% rename from hw5/oatprograms/gnomesort.oat rename to hw5/hw4programs/gnomesort.oat diff --git a/hw5/oatprograms/hashcode.oat b/hw5/hw4programs/hashcode.oat similarity index 100% rename from hw5/oatprograms/hashcode.oat rename to hw5/hw4programs/hashcode.oat diff --git a/hw5/oatprograms/heap.oat b/hw5/hw4programs/heap.oat similarity index 100% rename from hw5/oatprograms/heap.oat rename to hw5/hw4programs/heap.oat diff --git a/hw5/oatprograms/insertion_sort.oat b/hw5/hw4programs/insertion_sort.oat similarity index 95% rename from hw5/oatprograms/insertion_sort.oat rename to hw5/hw4programs/insertion_sort.oat index acbb6f4..c4bc2ae 100644 --- a/hw5/oatprograms/insertion_sort.oat +++ b/hw5/hw4programs/insertion_sort.oat @@ -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]) { diff --git a/hw5/oatprograms/is_prime.oat b/hw5/hw4programs/is_prime.oat similarity index 100% rename from hw5/oatprograms/is_prime.oat rename to hw5/hw4programs/is_prime.oat diff --git a/hw5/oatprograms/josh_joyce_test.oat b/hw5/hw4programs/josh_joyce_test.oat similarity index 100% rename from hw5/oatprograms/josh_joyce_test.oat rename to hw5/hw4programs/josh_joyce_test.oat diff --git a/hw5/oatprograms/kmp.oat b/hw5/hw4programs/kmp.oat similarity index 100% rename from hw5/oatprograms/kmp.oat rename to hw5/hw4programs/kmp.oat diff --git a/hw5/oatprograms/lcs.oat b/hw5/hw4programs/lcs.oat similarity index 100% rename from hw5/oatprograms/lcs.oat rename to hw5/hw4programs/lcs.oat diff --git a/hw5/oatprograms/leastsquare.oat b/hw5/hw4programs/leastsquare.oat similarity index 100% rename from hw5/oatprograms/leastsquare.oat rename to hw5/hw4programs/leastsquare.oat diff --git a/hw5/oatprograms/lfsr.oat b/hw5/hw4programs/lfsr.oat similarity index 95% rename from hw5/oatprograms/lfsr.oat rename to hw5/hw4programs/lfsr.oat index 1320b2a..f4ee995 100644 --- a/hw5/oatprograms/lfsr.oat +++ b/hw5/hw4programs/lfsr.oat @@ -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]; } diff --git a/hw5/oatprograms/lfsr2.oat b/hw5/hw4programs/lfsr2.oat similarity index 100% rename from hw5/oatprograms/lfsr2.oat rename to hw5/hw4programs/lfsr2.oat diff --git a/hw5/oatprograms/lib10.oat b/hw5/hw4programs/lib10.oat similarity index 100% rename from hw5/oatprograms/lib10.oat rename to hw5/hw4programs/lib10.oat diff --git a/hw5/oatprograms/lib11.oat b/hw5/hw4programs/lib11.oat similarity index 100% rename from hw5/oatprograms/lib11.oat rename to hw5/hw4programs/lib11.oat diff --git a/hw5/oatprograms/lib12.oat b/hw5/hw4programs/lib12.oat similarity index 100% rename from hw5/oatprograms/lib12.oat rename to hw5/hw4programs/lib12.oat diff --git a/hw5/oatprograms/lib13.oat b/hw5/hw4programs/lib13.oat similarity index 100% rename from hw5/oatprograms/lib13.oat rename to hw5/hw4programs/lib13.oat diff --git a/hw5/oatprograms/lib14.oat b/hw5/hw4programs/lib14.oat similarity index 100% rename from hw5/oatprograms/lib14.oat rename to hw5/hw4programs/lib14.oat diff --git a/hw5/oatprograms/lib15.oat b/hw5/hw4programs/lib15.oat similarity index 68% rename from hw5/oatprograms/lib15.oat rename to hw5/hw4programs/lib15.oat index 974359b..1ad6de3 100644 --- a/hw5/oatprograms/lib15.oat +++ b/hw5/hw4programs/lib15.oat @@ -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); } diff --git a/hw5/oatprograms/lib2.oat b/hw5/hw4programs/lib2.oat similarity index 100% rename from hw5/oatprograms/lib2.oat rename to hw5/hw4programs/lib2.oat diff --git a/hw5/oatprograms/lib3.oat b/hw5/hw4programs/lib3.oat similarity index 100% rename from hw5/oatprograms/lib3.oat rename to hw5/hw4programs/lib3.oat diff --git a/hw5/oatprograms/lib4.oat b/hw5/hw4programs/lib4.oat similarity index 100% rename from hw5/oatprograms/lib4.oat rename to hw5/hw4programs/lib4.oat diff --git a/hw5/oatprograms/lib5.oat b/hw5/hw4programs/lib5.oat similarity index 100% rename from hw5/oatprograms/lib5.oat rename to hw5/hw4programs/lib5.oat diff --git a/hw5/oatprograms/lib6.oat b/hw5/hw4programs/lib6.oat similarity index 100% rename from hw5/oatprograms/lib6.oat rename to hw5/hw4programs/lib6.oat diff --git a/hw5/oatprograms/lib7.oat b/hw5/hw4programs/lib7.oat similarity index 100% rename from hw5/oatprograms/lib7.oat rename to hw5/hw4programs/lib7.oat diff --git a/hw5/oatprograms/lib8.oat b/hw5/hw4programs/lib8.oat similarity index 100% rename from hw5/oatprograms/lib8.oat rename to hw5/hw4programs/lib8.oat diff --git a/hw5/oatprograms/lib9.oat b/hw5/hw4programs/lib9.oat similarity index 100% rename from hw5/oatprograms/lib9.oat rename to hw5/hw4programs/lib9.oat diff --git a/hw5/oatprograms/life.oat b/hw5/hw4programs/life.oat similarity index 86% rename from hw5/oatprograms/life.oat rename to hw5/hw4programs/life.oat index 81ce014..c67503c 100644 --- a/hw5/oatprograms/life.oat +++ b/hw5/hw4programs/life.oat @@ -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); } diff --git a/hw5/oatprograms/matrixmult.oat b/hw5/hw4programs/matrixmult.oat similarity index 100% rename from hw5/oatprograms/matrixmult.oat rename to hw5/hw4programs/matrixmult.oat diff --git a/hw5/oatprograms/maxsubsequence.oat b/hw5/hw4programs/maxsubsequence.oat similarity index 93% rename from hw5/oatprograms/maxsubsequence.oat rename to hw5/hw4programs/maxsubsequence.oat index 31b8ca1..5581eda 100644 --- a/hw5/oatprograms/maxsubsequence.oat +++ b/hw5/hw4programs/maxsubsequence.oat @@ -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;){ diff --git a/hw5/oatprograms/msort.oat b/hw5/hw4programs/msort.oat similarity index 97% rename from hw5/oatprograms/msort.oat rename to hw5/hw4programs/msort.oat index 7c576c6..a786960 100644 --- a/hw5/oatprograms/msort.oat +++ b/hw5/hw4programs/msort.oat @@ -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; diff --git a/hw5/oatprograms/msort2.oat b/hw5/hw4programs/msort2.oat similarity index 97% rename from hw5/oatprograms/msort2.oat rename to hw5/hw4programs/msort2.oat index a415ced..7ba3b4d 100644 --- a/hw5/oatprograms/msort2.oat +++ b/hw5/hw4programs/msort2.oat @@ -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; diff --git a/hw5/oatprograms/no_of_fac.oat b/hw5/hw4programs/no_of_fac.oat similarity index 94% rename from hw5/oatprograms/no_of_fac.oat rename to hw5/hw4programs/no_of_fac.oat index 1de54d6..8ded4de 100644 --- a/hw5/oatprograms/no_of_fac.oat +++ b/hw5/hw4programs/no_of_fac.oat @@ -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); +} diff --git a/hw5/oatprograms/path1.oat b/hw5/hw4programs/path1.oat similarity index 100% rename from hw5/oatprograms/path1.oat rename to hw5/hw4programs/path1.oat diff --git a/hw5/oatprograms/path2.oat b/hw5/hw4programs/path2.oat similarity index 100% rename from hw5/oatprograms/path2.oat rename to hw5/hw4programs/path2.oat diff --git a/hw5/oatprograms/path3.oat b/hw5/hw4programs/path3.oat similarity index 100% rename from hw5/oatprograms/path3.oat rename to hw5/hw4programs/path3.oat diff --git a/hw5/oatprograms/phase2_1.oat b/hw5/hw4programs/phase2_1.oat similarity index 100% rename from hw5/oatprograms/phase2_1.oat rename to hw5/hw4programs/phase2_1.oat diff --git a/hw5/oatprograms/qs_bs.oat b/hw5/hw4programs/qs_bs.oat similarity index 100% rename from hw5/oatprograms/qs_bs.oat rename to hw5/hw4programs/qs_bs.oat diff --git a/hw5/oatprograms/qsort.oat b/hw5/hw4programs/qsort.oat similarity index 100% rename from hw5/oatprograms/qsort.oat rename to hw5/hw4programs/qsort.oat diff --git a/hw5/oatprograms/regalloctest.oat b/hw5/hw4programs/regalloctest.oat similarity index 100% rename from hw5/oatprograms/regalloctest.oat rename to hw5/hw4programs/regalloctest.oat diff --git a/hw5/oatprograms/regalloctest2.oat b/hw5/hw4programs/regalloctest2.oat similarity index 100% rename from hw5/oatprograms/regalloctest2.oat rename to hw5/hw4programs/regalloctest2.oat diff --git a/hw5/oatprograms/regex.oat b/hw5/hw4programs/regex.oat similarity index 100% rename from hw5/oatprograms/regex.oat rename to hw5/hw4programs/regex.oat diff --git a/hw5/oatprograms/reverse.oat b/hw5/hw4programs/reverse.oat similarity index 100% rename from hw5/oatprograms/reverse.oat rename to hw5/hw4programs/reverse.oat diff --git a/hw5/oatprograms/rod_cutting.oat b/hw5/hw4programs/rod_cutting.oat similarity index 100% rename from hw5/oatprograms/rod_cutting.oat rename to hw5/hw4programs/rod_cutting.oat diff --git a/hw5/oatprograms/run1.oat b/hw5/hw4programs/run1.oat similarity index 100% rename from hw5/oatprograms/run1.oat rename to hw5/hw4programs/run1.oat diff --git a/hw5/oatprograms/run10.oat b/hw5/hw4programs/run10.oat similarity index 100% rename from hw5/oatprograms/run10.oat rename to hw5/hw4programs/run10.oat diff --git a/hw5/oatprograms/run11.oat b/hw5/hw4programs/run11.oat similarity index 100% rename from hw5/oatprograms/run11.oat rename to hw5/hw4programs/run11.oat diff --git a/hw5/oatprograms/run13.oat b/hw5/hw4programs/run13.oat similarity index 100% rename from hw5/oatprograms/run13.oat rename to hw5/hw4programs/run13.oat diff --git a/hw5/oatprograms/run14.oat b/hw5/hw4programs/run14.oat similarity index 74% rename from hw5/oatprograms/run14.oat rename to hw5/hw4programs/run14.oat index d556347..836a239 100644 --- a/hw5/oatprograms/run14.oat +++ b/hw5/hw4programs/run14.oat @@ -3,17 +3,17 @@ int f(int[] a) { } int g(int x) { - var arr = new int[3]{i->0}; + var arr = new int[3]; for (var i = 0; i < 3; i=i+1;) { arr[i] = x; } return arr[1]; } int program (int argc, string[] argv) { - var a = new int[3]{i->0}; + var a = new int[3]; for (var i=0; i < 3; i=i+1;) { a[i] = i; } - var arr = new int[4]{i->0}; + var arr = new int[4]; for (var i=0; i < 4; i=i+1;) { arr[i] = i*i; } - var arr0 = new int[3]{i->0}; + var arr0 = new int[3]; for (var i=0; i < 3; i=i+1;) { arr0[i] = 2*i; } return arr[3] + a[1] + f(arr0) + g(4); } diff --git a/hw5/hw4programs/run15.oat b/hw5/hw4programs/run15.oat new file mode 100644 index 0000000..b2608af --- /dev/null +++ b/hw5/hw4programs/run15.oat @@ -0,0 +1,20 @@ +int f(int[][] a) { + return a[1][1]; +} + +int g(int x) { + var arr = new int[][]{new int[]{x, x, x}, new int[]{x, x, x}, new int[]{x, x, x}}; + return arr[1][1]; +} + +int program (int argc, string[] argv) { + var a = new int[][]{new int[]{0,1,2},new int[]{0,1,2},new int[]{0,1,2}}; + var arr = new int[][]{new int[]{0*0, 0*1, 0*2, 0*3, 0*4}, + new int[]{1*0, 1*1, 1*2, 1*3, 1*4}, + new int[]{2*0, 2*1, 2*2, 2*3, 2*4}, + new int[]{3*0, 3*1, 3*2, 3*3, 3*4}}; + var arr0 = new int[][]{new int[]{0*0, 0*1, 0*2}, + new int[]{1*0, 1*1, 1*2}, + new int[]{2*0, 2*1, 2*2}}; + return arr[3][4] + a[1][2] + f(arr0) + g(4); +} diff --git a/hw5/hw4programs/run16.oat b/hw5/hw4programs/run16.oat new file mode 100644 index 0000000..077d1c2 --- /dev/null +++ b/hw5/hw4programs/run16.oat @@ -0,0 +1,9 @@ +int program (int argc, string[] argv) { + var x = 10; + var a = new int[][]{new int[]{x+0+0, x+0+1, x+0+2}, + new int[]{x+1+0, x+1+1, x+1+2}, + new int[]{x+2+0, x+2+1, x+2+2}}; + + var b = a; + return b[2][1]; +} diff --git a/hw5/oatprograms/run18.oat b/hw5/hw4programs/run18.oat similarity index 100% rename from hw5/oatprograms/run18.oat rename to hw5/hw4programs/run18.oat diff --git a/hw5/oatprograms/run19.oat b/hw5/hw4programs/run19.oat similarity index 100% rename from hw5/oatprograms/run19.oat rename to hw5/hw4programs/run19.oat diff --git a/hw5/oatprograms/run2.oat b/hw5/hw4programs/run2.oat similarity index 100% rename from hw5/oatprograms/run2.oat rename to hw5/hw4programs/run2.oat diff --git a/hw5/oatprograms/run20.oat b/hw5/hw4programs/run20.oat similarity index 100% rename from hw5/oatprograms/run20.oat rename to hw5/hw4programs/run20.oat diff --git a/hw5/oatprograms/run21.oat b/hw5/hw4programs/run21.oat similarity index 100% rename from hw5/oatprograms/run21.oat rename to hw5/hw4programs/run21.oat diff --git a/hw5/oatprograms/run22.oat b/hw5/hw4programs/run22.oat similarity index 100% rename from hw5/oatprograms/run22.oat rename to hw5/hw4programs/run22.oat diff --git a/hw5/oatprograms/run23.oat b/hw5/hw4programs/run23.oat similarity index 100% rename from hw5/oatprograms/run23.oat rename to hw5/hw4programs/run23.oat diff --git a/hw5/oatprograms/run24.oat b/hw5/hw4programs/run24.oat similarity index 100% rename from hw5/oatprograms/run24.oat rename to hw5/hw4programs/run24.oat diff --git a/hw5/oatprograms/run25.oat b/hw5/hw4programs/run25.oat similarity index 75% rename from hw5/oatprograms/run25.oat rename to hw5/hw4programs/run25.oat index 3d54e9e..330bc97 100644 --- a/hw5/oatprograms/run25.oat +++ b/hw5/hw4programs/run25.oat @@ -1,5 +1,5 @@ int program (int argc, string[] argv) { - var a = new int[3]{i -> 110}; + var a = new int[]{110, 110, 110}; var str = string_of_array (a); print_string (str); return 0; diff --git a/hw5/oatprograms/run26.oat b/hw5/hw4programs/run26.oat similarity index 100% rename from hw5/oatprograms/run26.oat rename to hw5/hw4programs/run26.oat diff --git a/hw5/oatprograms/run27.oat b/hw5/hw4programs/run27.oat similarity index 100% rename from hw5/oatprograms/run27.oat rename to hw5/hw4programs/run27.oat diff --git a/hw5/oatprograms/run28.oat b/hw5/hw4programs/run28.oat similarity index 100% rename from hw5/oatprograms/run28.oat rename to hw5/hw4programs/run28.oat diff --git a/hw5/oatprograms/run29.oat b/hw5/hw4programs/run29.oat similarity index 100% rename from hw5/oatprograms/run29.oat rename to hw5/hw4programs/run29.oat diff --git a/hw5/oatprograms/run3.oat b/hw5/hw4programs/run3.oat similarity index 100% rename from hw5/oatprograms/run3.oat rename to hw5/hw4programs/run3.oat diff --git a/hw5/oatprograms/run30.oat b/hw5/hw4programs/run30.oat similarity index 100% rename from hw5/oatprograms/run30.oat rename to hw5/hw4programs/run30.oat diff --git a/hw5/oatprograms/run31.oat b/hw5/hw4programs/run31.oat similarity index 100% rename from hw5/oatprograms/run31.oat rename to hw5/hw4programs/run31.oat diff --git a/hw5/oatprograms/run32.oat b/hw5/hw4programs/run32.oat similarity index 100% rename from hw5/oatprograms/run32.oat rename to hw5/hw4programs/run32.oat diff --git a/hw5/oatprograms/run33.oat b/hw5/hw4programs/run33.oat similarity index 100% rename from hw5/oatprograms/run33.oat rename to hw5/hw4programs/run33.oat diff --git a/hw5/oatprograms/run34.oat b/hw5/hw4programs/run34.oat similarity index 100% rename from hw5/oatprograms/run34.oat rename to hw5/hw4programs/run34.oat diff --git a/hw5/oatprograms/run35.oat b/hw5/hw4programs/run35.oat similarity index 100% rename from hw5/oatprograms/run35.oat rename to hw5/hw4programs/run35.oat diff --git a/hw5/oatprograms/run36.oat b/hw5/hw4programs/run36.oat similarity index 100% rename from hw5/oatprograms/run36.oat rename to hw5/hw4programs/run36.oat diff --git a/hw5/oatprograms/run37.oat b/hw5/hw4programs/run37.oat similarity index 100% rename from hw5/oatprograms/run37.oat rename to hw5/hw4programs/run37.oat diff --git a/hw5/oatprograms/run38.oat b/hw5/hw4programs/run38.oat similarity index 100% rename from hw5/oatprograms/run38.oat rename to hw5/hw4programs/run38.oat diff --git a/hw5/oatprograms/run39.oat b/hw5/hw4programs/run39.oat similarity index 100% rename from hw5/oatprograms/run39.oat rename to hw5/hw4programs/run39.oat diff --git a/hw5/oatprograms/run4.oat b/hw5/hw4programs/run4.oat similarity index 100% rename from hw5/oatprograms/run4.oat rename to hw5/hw4programs/run4.oat diff --git a/hw5/oatprograms/run40.oat b/hw5/hw4programs/run40.oat similarity index 100% rename from hw5/oatprograms/run40.oat rename to hw5/hw4programs/run40.oat diff --git a/hw5/oatprograms/run41.oat b/hw5/hw4programs/run41.oat similarity index 100% rename from hw5/oatprograms/run41.oat rename to hw5/hw4programs/run41.oat diff --git a/hw5/hw4programs/run42.oat b/hw5/hw4programs/run42.oat new file mode 100644 index 0000000..afaa70d --- /dev/null +++ b/hw5/hw4programs/run42.oat @@ -0,0 +1,16 @@ +int program(int argc, string[] argv) { + var a1=new int[][]{new int[1],new int[1],new int[1]}; + var a2=new int[][]{new int[1],new int[1],new int[1]}; + var a3=new int[][]{new int[1],new int[1],new int[1]}; + var a4=new int[][]{new int[1],new int[1],new int[1]}; + var a5=new int[]{0, 1, 2}; + a2[0] = a5; + a2[0][0] = 2; + a1 = a2; + a3 = a1; + a1 = a4; + a2 = a3; + a4 = a2; + a3 = a4; + return a3[0][0]; +} diff --git a/hw5/oatprograms/run43.oat b/hw5/hw4programs/run43.oat similarity index 100% rename from hw5/oatprograms/run43.oat rename to hw5/hw4programs/run43.oat diff --git a/hw5/hw4programs/run44.oat b/hw5/hw4programs/run44.oat new file mode 100644 index 0000000..3addb73 --- /dev/null +++ b/hw5/hw4programs/run44.oat @@ -0,0 +1,19 @@ +global str = string[][][][][][][][][][] null; + +int program (int argc, string[] argv) { + str = new string[][][][][][][][][][]{ + new string[][][][][][][][][]{ + new string[][][][][][][][]{ + new string[][][][][][][]{ + new string[][][][][][]{ + new string[][][][][]{ + new string[][][][]{ + new string[][][]{ + new string[][]{ + new string[]{ + "hello"}}}}}}}}}}; + + print_string (str[0][0][0][0][0][0][0][0][0][0]); + return 0; +} + diff --git a/hw5/oatprograms/run45.oat b/hw5/hw4programs/run45.oat similarity index 100% rename from hw5/oatprograms/run45.oat rename to hw5/hw4programs/run45.oat diff --git a/hw5/oatprograms/run46.oat b/hw5/hw4programs/run46.oat similarity index 100% rename from hw5/oatprograms/run46.oat rename to hw5/hw4programs/run46.oat diff --git a/hw5/oatprograms/run47.oat b/hw5/hw4programs/run47.oat similarity index 71% rename from hw5/oatprograms/run47.oat rename to hw5/hw4programs/run47.oat index c2b1032..631b9fc 100644 --- a/hw5/oatprograms/run47.oat +++ b/hw5/hw4programs/run47.oat @@ -6,6 +6,8 @@ int f() { } int program (int argc, string[] argv) { - var b = new int[f()]{i -> i}; + var b = new int[f()]; + b[0] = 0; + b[1] = 1; return a + b[0] + b[1]; } diff --git a/hw5/oatprograms/run48.oat b/hw5/hw4programs/run48.oat similarity index 70% rename from hw5/oatprograms/run48.oat rename to hw5/hw4programs/run48.oat index 789d22a..0eaf3bb 100644 --- a/hw5/oatprograms/run48.oat +++ b/hw5/hw4programs/run48.oat @@ -6,6 +6,8 @@ int f() { } int program (int argc, string[] argv) { - var b = new int[f()]{i -> f()}; + var b = new int[f()]; + b[0] = f(); + b[1] = f(); return a + b[0] + b[1]; } diff --git a/hw5/oatprograms/run49.oat b/hw5/hw4programs/run49.oat similarity index 100% rename from hw5/oatprograms/run49.oat rename to hw5/hw4programs/run49.oat diff --git a/hw5/oatprograms/run5.oat b/hw5/hw4programs/run5.oat similarity index 100% rename from hw5/oatprograms/run5.oat rename to hw5/hw4programs/run5.oat diff --git a/hw5/oatprograms/run50.oat b/hw5/hw4programs/run50.oat similarity index 100% rename from hw5/oatprograms/run50.oat rename to hw5/hw4programs/run50.oat diff --git a/hw5/oatprograms/run51.oat b/hw5/hw4programs/run51.oat similarity index 100% rename from hw5/oatprograms/run51.oat rename to hw5/hw4programs/run51.oat diff --git a/hw5/oatprograms/run52.oat b/hw5/hw4programs/run52.oat similarity index 100% rename from hw5/oatprograms/run52.oat rename to hw5/hw4programs/run52.oat diff --git a/hw5/oatprograms/run53.oat b/hw5/hw4programs/run53.oat similarity index 100% rename from hw5/oatprograms/run53.oat rename to hw5/hw4programs/run53.oat diff --git a/hw5/oatprograms/run54.oat b/hw5/hw4programs/run54.oat similarity index 100% rename from hw5/oatprograms/run54.oat rename to hw5/hw4programs/run54.oat diff --git a/hw5/oatprograms/run55.oat b/hw5/hw4programs/run55.oat similarity index 100% rename from hw5/oatprograms/run55.oat rename to hw5/hw4programs/run55.oat diff --git a/hw5/oatprograms/run56.oat b/hw5/hw4programs/run56.oat similarity index 100% rename from hw5/oatprograms/run56.oat rename to hw5/hw4programs/run56.oat diff --git a/hw5/oatprograms/run6.oat b/hw5/hw4programs/run6.oat similarity index 100% rename from hw5/oatprograms/run6.oat rename to hw5/hw4programs/run6.oat diff --git a/hw5/oatprograms/run60.oat b/hw5/hw4programs/run60.oat similarity index 100% rename from hw5/oatprograms/run60.oat rename to hw5/hw4programs/run60.oat diff --git a/hw5/oatprograms/run61.oat b/hw5/hw4programs/run61.oat similarity index 100% rename from hw5/oatprograms/run61.oat rename to hw5/hw4programs/run61.oat diff --git a/hw5/oatprograms/run7.oat b/hw5/hw4programs/run7.oat similarity index 100% rename from hw5/oatprograms/run7.oat rename to hw5/hw4programs/run7.oat diff --git a/hw5/oatprograms/run8.oat b/hw5/hw4programs/run8.oat similarity index 100% rename from hw5/oatprograms/run8.oat rename to hw5/hw4programs/run8.oat diff --git a/hw5/oatprograms/run9.oat b/hw5/hw4programs/run9.oat similarity index 100% rename from hw5/oatprograms/run9.oat rename to hw5/hw4programs/run9.oat diff --git a/hw5/oatprograms/runtime-fail1.oat b/hw5/hw4programs/runtime-fail1.oat similarity index 100% rename from hw5/oatprograms/runtime-fail1.oat rename to hw5/hw4programs/runtime-fail1.oat diff --git a/hw5/oatprograms/runtime-fail2.oat b/hw5/hw4programs/runtime-fail2.oat similarity index 100% rename from hw5/oatprograms/runtime-fail2.oat rename to hw5/hw4programs/runtime-fail2.oat diff --git a/hw5/oatprograms/runtime-fail3.oat b/hw5/hw4programs/runtime-fail3.oat similarity index 100% rename from hw5/oatprograms/runtime-fail3.oat rename to hw5/hw4programs/runtime-fail3.oat diff --git a/hw5/oatprograms/runtime-fail4.oat b/hw5/hw4programs/runtime-fail4.oat similarity index 100% rename from hw5/oatprograms/runtime-fail4.oat rename to hw5/hw4programs/runtime-fail4.oat diff --git a/hw5/oatprograms/selectionsort.oat b/hw5/hw4programs/selectionsort.oat similarity index 100% rename from hw5/oatprograms/selectionsort.oat rename to hw5/hw4programs/selectionsort.oat diff --git a/hw5/hw4programs/setg.oat b/hw5/hw4programs/setg.oat new file mode 100644 index 0000000..0976d8d --- /dev/null +++ b/hw5/hw4programs/setg.oat @@ -0,0 +1,15 @@ +global x = 42; +int set_x(int y) { + var z = 0; + while (z < y) { + z = z + 1; + if (z == 37) { + return z; + } + } + return 0; +} +int program (int argc, string[] argv) { + x = set_x(30); + print_int(x); +} diff --git a/hw5/oatprograms/shortest_path_matrix.oat b/hw5/hw4programs/shortest_path_matrix.oat similarity index 100% rename from hw5/oatprograms/shortest_path_matrix.oat rename to hw5/hw4programs/shortest_path_matrix.oat diff --git a/hw5/oatprograms/sieve.oat b/hw5/hw4programs/sieve.oat similarity index 92% rename from hw5/oatprograms/sieve.oat rename to hw5/hw4programs/sieve.oat index 9f1673b..56ee38f 100644 --- a/hw5/oatprograms/sieve.oat +++ b/hw5/hw4programs/sieve.oat @@ -1,5 +1,5 @@ int sieve(int n) { - var arr = new bool[n]{i->false}; + var arr = new bool[n]; for (var i=0; i < n; i=i+1;) { arr[i] = true; } arr[0] = false; diff --git a/hw5/oatprograms/sqrt.oat b/hw5/hw4programs/sqrt.oat similarity index 100% rename from hw5/oatprograms/sqrt.oat rename to hw5/hw4programs/sqrt.oat diff --git a/hw5/oatprograms/tc1.oat b/hw5/hw4programs/tc1.oat similarity index 100% rename from hw5/oatprograms/tc1.oat rename to hw5/hw4programs/tc1.oat diff --git a/hw5/oatprograms/tc10.oat b/hw5/hw4programs/tc10.oat similarity index 100% rename from hw5/oatprograms/tc10.oat rename to hw5/hw4programs/tc10.oat diff --git a/hw5/oatprograms/tc11.oat b/hw5/hw4programs/tc11.oat similarity index 100% rename from hw5/oatprograms/tc11.oat rename to hw5/hw4programs/tc11.oat diff --git a/hw5/oatprograms/tc12.oat b/hw5/hw4programs/tc12.oat similarity index 100% rename from hw5/oatprograms/tc12.oat rename to hw5/hw4programs/tc12.oat diff --git a/hw5/oatprograms/tc13.oat b/hw5/hw4programs/tc13.oat similarity index 100% rename from hw5/oatprograms/tc13.oat rename to hw5/hw4programs/tc13.oat diff --git a/hw5/oatprograms/tc14.oat b/hw5/hw4programs/tc14.oat similarity index 100% rename from hw5/oatprograms/tc14.oat rename to hw5/hw4programs/tc14.oat diff --git a/hw5/oatprograms/tc15.oat b/hw5/hw4programs/tc15.oat similarity index 100% rename from hw5/oatprograms/tc15.oat rename to hw5/hw4programs/tc15.oat diff --git a/hw5/oatprograms/tc16.oat b/hw5/hw4programs/tc16.oat similarity index 100% rename from hw5/oatprograms/tc16.oat rename to hw5/hw4programs/tc16.oat diff --git a/hw5/oatprograms/tc17.oat b/hw5/hw4programs/tc17.oat similarity index 100% rename from hw5/oatprograms/tc17.oat rename to hw5/hw4programs/tc17.oat diff --git a/hw5/oatprograms/tc18.oat b/hw5/hw4programs/tc18.oat similarity index 100% rename from hw5/oatprograms/tc18.oat rename to hw5/hw4programs/tc18.oat diff --git a/hw5/oatprograms/tc19.oat b/hw5/hw4programs/tc19.oat similarity index 100% rename from hw5/oatprograms/tc19.oat rename to hw5/hw4programs/tc19.oat diff --git a/hw5/oatprograms/tc2.oat b/hw5/hw4programs/tc2.oat similarity index 100% rename from hw5/oatprograms/tc2.oat rename to hw5/hw4programs/tc2.oat diff --git a/hw5/oatprograms/tc20.oat b/hw5/hw4programs/tc20.oat similarity index 100% rename from hw5/oatprograms/tc20.oat rename to hw5/hw4programs/tc20.oat diff --git a/hw5/oatprograms/tc3.oat b/hw5/hw4programs/tc3.oat similarity index 100% rename from hw5/oatprograms/tc3.oat rename to hw5/hw4programs/tc3.oat diff --git a/hw5/oatprograms/tc4.oat b/hw5/hw4programs/tc4.oat similarity index 100% rename from hw5/oatprograms/tc4.oat rename to hw5/hw4programs/tc4.oat diff --git a/hw5/oatprograms/tc5.oat b/hw5/hw4programs/tc5.oat similarity index 100% rename from hw5/oatprograms/tc5.oat rename to hw5/hw4programs/tc5.oat diff --git a/hw5/oatprograms/tc6.oat b/hw5/hw4programs/tc6.oat similarity index 100% rename from hw5/oatprograms/tc6.oat rename to hw5/hw4programs/tc6.oat diff --git a/hw5/oatprograms/tc7.oat b/hw5/hw4programs/tc7.oat similarity index 100% rename from hw5/oatprograms/tc7.oat rename to hw5/hw4programs/tc7.oat diff --git a/hw5/oatprograms/tc8.oat b/hw5/hw4programs/tc8.oat similarity index 100% rename from hw5/oatprograms/tc8.oat rename to hw5/hw4programs/tc8.oat diff --git a/hw5/oatprograms/tc9.oat b/hw5/hw4programs/tc9.oat similarity index 100% rename from hw5/oatprograms/tc9.oat rename to hw5/hw4programs/tc9.oat diff --git a/hw5/oatprograms/tc_ok1.oat b/hw5/hw4programs/tc_ok1.oat similarity index 100% rename from hw5/oatprograms/tc_ok1.oat rename to hw5/hw4programs/tc_ok1.oat diff --git a/hw5/oatprograms/tc_ok2.oat b/hw5/hw4programs/tc_ok2.oat similarity index 100% rename from hw5/oatprograms/tc_ok2.oat rename to hw5/hw4programs/tc_ok2.oat diff --git a/hw5/oatprograms/tc_ok4.oat b/hw5/hw4programs/tc_ok4.oat similarity index 100% rename from hw5/oatprograms/tc_ok4.oat rename to hw5/hw4programs/tc_ok4.oat diff --git a/hw5/oatprograms/tc_ok5.oat b/hw5/hw4programs/tc_ok5.oat similarity index 100% rename from hw5/oatprograms/tc_ok5.oat rename to hw5/hw4programs/tc_ok5.oat diff --git a/hw5/oatprograms/tc_ok6.oat b/hw5/hw4programs/tc_ok6.oat similarity index 100% rename from hw5/oatprograms/tc_ok6.oat rename to hw5/hw4programs/tc_ok6.oat diff --git a/hw5/oatprograms/tc_ok7.oat b/hw5/hw4programs/tc_ok7.oat similarity index 100% rename from hw5/oatprograms/tc_ok7.oat rename to hw5/hw4programs/tc_ok7.oat diff --git a/hw5/oatprograms/tc_ok8.oat b/hw5/hw4programs/tc_ok8.oat similarity index 100% rename from hw5/oatprograms/tc_ok8.oat rename to hw5/hw4programs/tc_ok8.oat diff --git a/hw5/oatprograms/toascii.oat b/hw5/hw4programs/toascii.oat similarity index 100% rename from hw5/oatprograms/toascii.oat rename to hw5/hw4programs/toascii.oat diff --git a/hw5/oatprograms/toposort.oat b/hw5/hw4programs/toposort.oat similarity index 100% rename from hw5/oatprograms/toposort.oat rename to hw5/hw4programs/toposort.oat diff --git a/hw5/oatprograms/union_find.oat b/hw5/hw4programs/union_find.oat similarity index 100% rename from hw5/oatprograms/union_find.oat rename to hw5/hw4programs/union_find.oat diff --git a/hw5/oatprograms/xor_bool.oat b/hw5/hw4programs/xor_bool.oat similarity index 100% rename from hw5/oatprograms/xor_bool.oat rename to hw5/hw4programs/xor_bool.oat diff --git a/hw5/oatprograms/xor_shift.oat b/hw5/hw4programs/xor_shift.oat similarity index 93% rename from hw5/oatprograms/xor_shift.oat rename to hw5/hw4programs/xor_shift.oat index 7d08dae..3b81f31 100644 --- a/hw5/oatprograms/xor_shift.oat +++ b/hw5/hw4programs/xor_shift.oat @@ -16,7 +16,7 @@ int xor_shift_plus (int[] s) { } int program (int argc, string[] argv) { - var seed = new int[2]{i->0}; + var seed = new int[2]; for (var i=0; i < 2; i=i+1;) { seed[i] = 100 * (i + 1); } print_int(xor_shift_plus(seed)); diff --git a/hw5/team.txt b/hw5/hw5.opam similarity index 100% rename from hw5/team.txt rename to hw5/hw5.opam diff --git a/hw5/hw5programs/apoth_composition.oat b/hw5/hw5programs/apoth_composition.oat index 064bba4..4bccba5 100644 --- a/hw5/hw5programs/apoth_composition.oat +++ b/hw5/hw5programs/apoth_composition.oat @@ -57,4 +57,4 @@ int program(int argc, string[] argv) { } } return dog.food + numVisited; -} +} \ No newline at end of file diff --git a/hw5/hw5programs/array_oob.oat b/hw5/hw5programs/array_oob.oat new file mode 100644 index 0000000..77d8f06 --- /dev/null +++ b/hw5/hw5programs/array_oob.oat @@ -0,0 +1,8 @@ +int program(int arc, string[] args) { + var arr = new int[3]; + print_int(arr[0]); + print_int(arr[1]); + print_int(arr[2]); + print_int(arr[3]); + return 0; +} \ No newline at end of file diff --git a/hw5/hw5programs/burowski_bfs.oat b/hw5/hw5programs/burowski_bfs.oat index 157ca30..05ac27f 100644 --- a/hw5/hw5programs/burowski_bfs.oat +++ b/hw5/hw5programs/burowski_bfs.oat @@ -171,4 +171,4 @@ int program (int argc, string[] argv) { bfs(there); return 0; -} +} \ No newline at end of file diff --git a/hw5/hw5programs/compile_array_init.oat b/hw5/hw5programs/compile_array_init.oat new file mode 100644 index 0000000..e3db43c --- /dev/null +++ b/hw5/hw5programs/compile_array_init.oat @@ -0,0 +1,7 @@ +int program(int argc, string[] argv) { + var x = new int[]?[2]; + if (x[0] == int[] null & x[1] == int[] null) { + return 2; + } + return 0; +} diff --git a/hw5/oatprograms/conquest.oat b/hw5/hw5programs/conquest.oat similarity index 88% rename from hw5/oatprograms/conquest.oat rename to hw5/hw5programs/conquest.oat index 275122d..c92bdbb 100644 --- a/hw5/oatprograms/conquest.oat +++ b/hw5/hw5programs/conquest.oat @@ -63,7 +63,9 @@ void dfs (int[][] arr, int[][] visited, int row, int col, int i, int j) { } int connected (int[][] arr, int row, int col) { - var visited = new int[][row]{i-> new int[col]{j->0}}; + var visited = new int[][row]{ i -> + new int[col] + }; var counter = 0; for (var i = 0; i < row; i = i + 1;) { @@ -99,15 +101,20 @@ int program (int argc, string[] argv) { new int[]{0, 1, 0}, new int[]{1, 0, 1}}; - var none_conquered = new int[][four()]{i-> new int[2]{j->actual_341_midterm_score[0]}}; + var none_conquered = new int[][four()]{i -> + new int[]{ + actual_341_midterm_score[0], + actual_341_midterm_score[0] + } + }; - var all_conquered = new int[][6]{i->new int[6]{j -> i*0+1}}; + var all_conquered = new int[][6]{ i -> + new int[]{1, 1, 1, 1, 1, 1} + }; var island = new int[][] {new int[]{}}; - var emptyland = new int[][1]{i -> - new int[1]{ j -> - asian_brother_of_foo_named_fui(professor,kesha_to_fling,ideal_341_midterm_score[0])[1] - } + var emptyland = new int[][]{ + new int[]{asian_brother_of_foo_named_fui(professor,kesha_to_fling,ideal_341_midterm_score[0])[1]} }; all_conquered = all_conquered; diff --git a/hw5/hw5programs/field_overlap.oat b/hw5/hw5programs/field_overlap.oat new file mode 100644 index 0000000..daca05c --- /dev/null +++ b/hw5/hw5programs/field_overlap.oat @@ -0,0 +1,13 @@ +struct S1 { + int x; + int y +} +struct S2 { + int y; + int z +} +int program (int argc, string[] argv) { + var a = new S2{y = 1; z = 2}; + print_int(a.y); + return 0; +} diff --git a/hw5/hw5programs/for_scope.oat b/hw5/hw5programs/for_scope.oat new file mode 100644 index 0000000..d4afd36 --- /dev/null +++ b/hw5/hw5programs/for_scope.oat @@ -0,0 +1,8 @@ +int program (int argc, string[] argv) { + var r = 0; + for(var z = 102, var y = z + 10; z < y; z = z + 1;) { + r = r + 2; + } + print_int(r); + return 0; +} \ No newline at end of file diff --git a/hw5/hw5programs/gregor.oat b/hw5/hw5programs/gregor.oat deleted file mode 100644 index b789f8e..0000000 --- a/hw5/hw5programs/gregor.oat +++ /dev/null @@ -1,5 +0,0 @@ -int program (int argc, string[] argv) { - var id = "" -} - -int id(int x) { return x; } diff --git a/hw5/hw5programs/ifq1.oat b/hw5/hw5programs/ifq1.oat new file mode 100644 index 0000000..5d2c351 --- /dev/null +++ b/hw5/hw5programs/ifq1.oat @@ -0,0 +1,11 @@ +int program (int argc, string[] argv) { + var x = int[] null; + x = new int[3]{i -> 0}; + var z = 0; + if? (int[] y = x) { + z = 4; + } else { + z = 5; + } + return z; +} diff --git a/hw5/hw5programs/ifq2.oat b/hw5/hw5programs/ifq2.oat new file mode 100644 index 0000000..9c809e4 --- /dev/null +++ b/hw5/hw5programs/ifq2.oat @@ -0,0 +1,10 @@ +int program (int argc, string[] argv) { + var x = int[] null; + var z = 0; + if? (int[] y = x) { + z = 4; + } else { + z = 5; + } + return z; +} diff --git a/hw5/hw5programs/ifq3.oat b/hw5/hw5programs/ifq3.oat new file mode 100644 index 0000000..783a464 --- /dev/null +++ b/hw5/hw5programs/ifq3.oat @@ -0,0 +1,16 @@ +int sum(int[]? arr) { + var z = 0; + if?(int[] a = arr) { + for(var i = 0; i void f -} - -void print(int val) { - print_string(string_cat("->", string_of_int(val))); - return; -} - -void in_order_traverse(Tree tree) { - tree.f(tree.val); - if(tree.left.val != 0) { - in_order_traverse(tree.left); - } - - if(tree.right.val != 0) { - in_order_traverse(tree.right); - } - return; -} - -void pre_order_traverse(Tree tree) { - if(tree.left.val != 0) { - pre_order_traverse(tree.left); - } - - tree.f(tree.val); - - if(tree.right.val != 0) { - pre_order_traverse(tree.right); - } - return; -} - -void post_order_traverse(Tree tree) { - if(tree.left.val != 0) { - post_order_traverse(tree.left); - } - - if(tree.right.val != 0) { - post_order_traverse(tree.right); - } - - tree.f(tree.val); - return; -} - -int program(int argc, string[] argv) { - var nullchild = new Tree { val = 0; left = Tree null; right = Tree null; f = print}; - var rightchild = new Tree { val = 1; left = nullchild; right = nullchild; f = print }; - var leftchild = new Tree { val = 1; left = nullchild; right = nullchild; f = print }; - var tree = new Tree { val = 2; left = leftchild; right = rightchild; f = print }; - - pre_order_traverse(tree); - in_order_traverse(tree); - post_order_traverse(tree); - return 0; +struct Tree { + int val; + Tree left; + Tree right; + (int) -> void f +} + +void print(int val) { + print_string(string_cat("->", string_of_int(val))); + return; +} + +void in_order_traverse(Tree tree) { + tree.f(tree.val); + if(tree.left.val != 0) { + in_order_traverse(tree.left); + } + + if(tree.right.val != 0) { + in_order_traverse(tree.right); + } + return; +} + +void pre_order_traverse(Tree tree) { + if(tree.left.val != 0) { + pre_order_traverse(tree.left); + } + + tree.f(tree.val); + + if(tree.right.val != 0) { + pre_order_traverse(tree.right); + } + return; +} + +void post_order_traverse(Tree tree) { + if(tree.left.val != 0) { + post_order_traverse(tree.left); + } + + if(tree.right.val != 0) { + post_order_traverse(tree.right); + } + + tree.f(tree.val); + return; +} + +int program(int argc, string[] argv) { + var nullchild = new Tree { val = 0; left = Tree null; right = Tree null; f = print}; + var rightchild = new Tree { val = 1; left = nullchild; right = nullchild; f = print }; + var leftchild = new Tree { val = 1; left = nullchild; right = nullchild; f = print }; + var tree = new Tree { val = 2; left = leftchild; right = rightchild; f = print }; + + pre_order_traverse(tree); + in_order_traverse(tree); + post_order_traverse(tree); + return 0; } \ No newline at end of file diff --git a/hw5/hw5programs/maale_odd_even.oat b/hw5/hw5programs/maale_odd_even.oat index 2c2b79b..ef58e55 100644 --- a/hw5/hw5programs/maale_odd_even.oat +++ b/hw5/hw5programs/maale_odd_even.oat @@ -1,35 +1,35 @@ -int[] oddevensort (int[] input, int len) { - var sorted = false; - while(!sorted) { - sorted = true; - for(var i = 1; i < len - 1; i = i + 2;) { - if(input[i] > input[i + 1]) { - var temp = input[i]; - input[i] = input[i + 1]; - input[i + 1] = temp; - sorted = false; - } - } - - for(var j = 0; j < len - 1; j = j + 2;) { - if(input[j] > input[j+1]) { - var temp = input[j]; - input[j] = input[j + 1]; - input[j + 1] = temp; - sorted = false; - } - } - } - return input; -} - -int program (int argc, string[] argv) { - var arr = new int[]{ 5, 200, 1, 65, 30, 99, 2, 0 }; - var len = 8; - var sorted = oddevensort(arr, len); - for(var i=0; i input[i + 1]) { + var temp = input[i]; + input[i] = input[i + 1]; + input[i + 1] = temp; + sorted = false; + } + } + + for(var j = 0; j < len - 1; j = j + 2;) { + if(input[j] > input[j+1]) { + var temp = input[j]; + input[j] = input[j + 1]; + input[j + 1] = temp; + sorted = false; + } + } + } + return input; +} + +int program (int argc, string[] argv) { + var arr = new int[]{ 5, 200, 1, 65, 30, 99, 2, 0 }; + var len = 8; + var sorted = oddevensort(arr, len); + for(var i=0; i new string[1]{i10 -> "hello"}}}}}}}}}}; - print_string (str[0][0][0][0][0][0][0][0][0][0]); + if?(string[][][][][][][][][][] x = str) { + print_string (x[0][0][0][0][0][0][0][0][0][0]); + } return 0; } diff --git a/hw5/hw5programs/tc_correct_array2.oat b/hw5/hw5programs/tc_correct_array2.oat new file mode 100644 index 0000000..3b6a1a2 --- /dev/null +++ b/hw5/hw5programs/tc_correct_array2.oat @@ -0,0 +1,4 @@ +int f() { + var x = new int[]?[3]; + return 2; +} diff --git a/hw5/hw5programs/tc_correct_array3.oat b/hw5/hw5programs/tc_correct_array3.oat new file mode 100644 index 0000000..064cbe2 --- /dev/null +++ b/hw5/hw5programs/tc_correct_array3.oat @@ -0,0 +1,4 @@ +int f() { + var x = new string[]?[2]; + return 2; +} diff --git a/hw5/hw5programs/tc_error_global_fptr_scope.oat b/hw5/hw5programs/tc_correct_global_fptr_scope.oat similarity index 100% rename from hw5/hw5programs/tc_error_global_fptr_scope.oat rename to hw5/hw5programs/tc_correct_global_fptr_scope.oat diff --git a/hw5/hw5programs/tc_eq1.oat b/hw5/hw5programs/tc_eq1.oat new file mode 100644 index 0000000..531827b --- /dev/null +++ b/hw5/hw5programs/tc_eq1.oat @@ -0,0 +1,14 @@ +struct S {} +struct T {} + +int program(int arc, string[] args) { + var z = 0; + var s = new S{}; + var t = new T{}; + if (s == t) { + z = 17; + } else { + z = 3; + } + return z; +} \ No newline at end of file diff --git a/hw5/hw5programs/tc_eq2.oat b/hw5/hw5programs/tc_eq2.oat new file mode 100644 index 0000000..e80b0e9 --- /dev/null +++ b/hw5/hw5programs/tc_eq2.oat @@ -0,0 +1,14 @@ +struct S {int x; bool y} +struct T {int x; bool y} + +int program(int argc, string[] args) { + var z = 0; + var s = new S{x=3;y=true}; + var t = new T{x=3;y=true}; + if (s == t) { + z = 17; + } else { + z = 3; + } + return z; +} \ No newline at end of file diff --git a/hw5/hw5programs/tc_error_array3.oat b/hw5/hw5programs/tc_error_array3.oat new file mode 100644 index 0000000..4f39483 --- /dev/null +++ b/hw5/hw5programs/tc_error_array3.oat @@ -0,0 +1,4 @@ +int f() { + var x = new int[][3]; + return 2; +} diff --git a/hw5/hw5programs/tc_error_array4.oat b/hw5/hw5programs/tc_error_array4.oat new file mode 100644 index 0000000..ded25b0 --- /dev/null +++ b/hw5/hw5programs/tc_error_array4.oat @@ -0,0 +1,4 @@ +int f() { + var x = new string[][2]; + return 2; +} diff --git a/hw5/hw5programs/tc_struct_null_field.oat b/hw5/hw5programs/tc_struct_null_field.oat new file mode 100644 index 0000000..cb59987 --- /dev/null +++ b/hw5/hw5programs/tc_struct_null_field.oat @@ -0,0 +1,18 @@ +struct A { + int x +} + +struct B { + A? a /* can be null */ +} + +int program(int argc, string[] args) { + var b = new B{a=A null}; + b.a = new A{x = 3}; + if? (A a2 = b.a) { + return a2.x; + } + b.a = A null; + return 0; +} + diff --git a/hw5/hw5programs/tc_subtyping7.oat b/hw5/hw5programs/tc_subtyping7.oat index 596821b..eb46c68 100644 --- a/hw5/hw5programs/tc_subtyping7.oat +++ b/hw5/hw5programs/tc_subtyping7.oat @@ -14,7 +14,7 @@ B g((C) -> B f) { return f(c); } -int program(string[] args) { +int program(int argc, string[] args) { var b = g(f); return b.y; } \ No newline at end of file diff --git a/hw5/hw5programs/tc_subtyping8.oat b/hw5/hw5programs/tc_subtyping8.oat index 8813494..5e0c8a0 100644 --- a/hw5/hw5programs/tc_subtyping8.oat +++ b/hw5/hw5programs/tc_subtyping8.oat @@ -13,7 +13,7 @@ void g((C) -> B f) { return; } -int program(string[] args) { +int program(int argc, string[] args) { g(f); return 0; } \ No newline at end of file diff --git a/hw5/hw5programs/tc_subtyping9.oat b/hw5/hw5programs/tc_subtyping9.oat index 2091e53..bd030bd 100644 --- a/hw5/hw5programs/tc_subtyping9.oat +++ b/hw5/hw5programs/tc_subtyping9.oat @@ -13,7 +13,7 @@ void g((C) -> B? f) { return; } -int program(string[] args) { +int program(int argc, string[] args) { g(f); return 0; } \ No newline at end of file diff --git a/hw5/lib/ll/dune b/hw5/lib/ll/dune new file mode 100644 index 0000000..74784a5 --- /dev/null +++ b/hw5/lib/ll/dune @@ -0,0 +1,7 @@ +(library + (name ll) + (modules ll llutil lllexer llparser llinterp) + (wrapped false)) + +(ocamllex lllexer) +(menhir (modules llparser)) diff --git a/hw5/lib/ll/ll-original.ml b/hw5/lib/ll/ll-original.ml new file mode 100644 index 0000000..c0acb18 --- /dev/null +++ b/hw5/lib/ll/ll-original.ml @@ -0,0 +1,81 @@ +(* LLVMlite: A simplified subset of the LLVM IR *) + +type uid = string (* Local identifiers *) +type gid = string (* Global identifiers *) +type tid = string (* Named types *) +type lbl = string (* Labels *) + +(* LLVM IR types *) +type ty = + | Void (* mix of unit/bottom from C *) + | I1 | I8 | I64 (* integer types *) + | Ptr of ty (* t* *) + | Struct of ty list (* { t1, t2, ... , tn } *) + | Array of int * ty (* [ NNN x t ] *) + | Fun of fty (* t1, ..., tn -> tr *) + | Namedt of tid (* named type aliases *) + +(* Function type: argument types and return type *) +and fty = ty list * ty + +(* Syntactic Values *) +type operand = + | Null (* null pointer *) + | Const of int64 (* integer constant *) + | Gid of gid (* A global identifier *) + | Id of uid (* A local identifier *) + +(* Type-annotated operands *) + +(* Binary operations *) +type bop = Add | Sub | Mul | Shl | Lshr | Ashr | And | Or | Xor + +(* Comparison Operators *) +type cnd = Eq | Ne | Slt | Sle | Sgt | Sge + +(* Instructions *) +type insn = + | Binop of bop * ty * operand * operand (* bop ty %o1, %o2 *) + | Alloca of ty (* alloca ty *) + | Load of ty * operand (* load ty %u *) + | Store of ty * operand * operand (* store ty %t, ty* %u *) + | Icmp of cnd * ty * operand * operand (* icmp %s ty %s, %s *) + | Call of ty * operand * (ty * operand) list (* fn(%1, %2, ...) *) + | Bitcast of ty * operand * ty (* bitcast ty1 %u to ty2 *) + | Gep of ty * operand * operand list (* getelementptr ty* %u, i64 %vi, ... *) + +(* Block terminators *) +type terminator = + | Ret of ty * operand option (* ret i64 %s *) + | Br of lbl (* br label %lbl *) + | Cbr of operand * lbl * lbl (* br i1 %s, label %l1, label %l2 *) + +(* Basic blocks *) +type block = { insns: (uid * insn) list; terminator: uid * terminator } + +(* Control Flow Graph: a pair of an entry block and a set labeled blocks *) +type cfg = block * (lbl * block) list + +(* Function declarations *) +type fdecl = { fty: fty; param: uid list; cfg: cfg } + +(* Initializers for global data *) +type ginit = + | GNull (* null literal *) + | GGid of gid (* reference another global *) + | GInt of int64 (* global integer value *) + | GString of string (* constant global string *) + | GArray of gdecl list (* global array *) + | GStruct of gdecl list (* global struct *) + +(* Global declaration *) +and gdecl = ty * ginit + +(* LLVMlite programs *) +type prog = + { tdecls: (tid * ty) list (* named types *) + ; gdecls: (gid * gdecl) list (* global data *) + ; fdecls: (gid * fdecl) list (* code *) + ; edecls: (gid * ty) list (* external declarations *) + } + diff --git a/hw5/ll/ll.ml b/hw5/lib/ll/ll.ml similarity index 90% rename from hw5/ll/ll.ml rename to hw5/lib/ll/ll.ml index 9cd2ff8..3b7ddfd 100644 --- a/hw5/ll/ll.ml +++ b/hw5/lib/ll/ll.ml @@ -94,5 +94,7 @@ type ginit = type gdecl = ty * ginit (* LLVMlite Programs *) -type prog = { tdecls : (tid * ty) list; gdecls : (gid * gdecl) list; - fdecls : (gid * fdecl) list; edecls : (gid * ty) list } +type prog = { tdecls : (tid * ty) list; + gdecls : (gid * gdecl) list; + fdecls : (gid * fdecl) list; + edecls : (gid * ty) list } diff --git a/hw5/lib/ll/llinterp.ml b/hw5/lib/ll/llinterp.ml new file mode 100644 index 0000000..3fd39a1 --- /dev/null +++ b/hw5/lib/ll/llinterp.ml @@ -0,0 +1,478 @@ +open Ll +open Llutil + +(* LLVMlite interpreter *) + +type mid = int (* memory block id *) +type fid = int (* stack frame id *) +type idx = int (* index *) + +(* Memory block identifier *) +type bid = GlobId of gid + | HeapId of mid + | StckId of fid + | NullId + +(* Pointers are tagged with a description of the block they reference + offsets are represented as paths into memory values *) +type ptr = ty * bid * idx list + +(* "Simple" or stack values *) +type sval = + | VUndef + | VInt of int64 + | VPtr of ptr + +(* Memory values *) +type mtree = MWord of sval + | MStr of string + | MNode of mval +and mval = mtree list + +(* Locals *) +type locals = uid -> sval + +(* The memory state *) +type config = + { globals : (gid * mval) list + ; heap : (mid * mval) list + ; stack : (fid * mval) list + } + +(* Create memory value for global declaration *) +let mval_of_gdecl (gd:gdecl) : mval = + let rec mtree_of_gdecl : gdecl -> mtree = function + | ty, GNull -> MWord (VPtr (ty, NullId, [0])) + | ty, GGid g -> MWord (VPtr (ty, GlobId g, [0])) + | _, GBitcast (t1, v, _) -> mtree_of_gdecl (t1, v) + | _, GInt i -> MWord (VInt i) + | _, GString s -> MStr s + | _, GArray gs + | _, GStruct gs -> MNode (List.map mtree_of_gdecl gs) + in [mtree_of_gdecl gd] + +(* Create fully undefined memory value for a type *) +let mval_of_ty (nt:tid -> ty) (t:ty) : mval = + let rec mtree_of_ty : ty -> mtree = function + | I1 | I8 | I64 | Ptr _ -> MWord VUndef + | Array (n, I8) -> MStr (String.make n '\x00') + | Array (n, _t) -> MNode Array.(make n (MWord VUndef) |> to_list) + | Struct ts -> MNode (List.map mtree_of_ty ts) + | Fun _ | Void -> failwith "mval_of_ty: mval for bad type" + | Namedt id -> mtree_of_ty (nt id) + in [mtree_of_ty t] + + +(* Printing machine states *) +let mapcat s f l = String.concat s @@ List.map f l +let prefix p f a = p ^ f a +let ( ^. ) s t = if s = "" || t = "" then "" else s ^ t +let pp = Printf.sprintf + +let string_of_bid = function + | GlobId gid -> "@" ^ gid + | HeapId mid -> "M" ^ (string_of_int mid) + | StckId fid -> "S" ^ (string_of_int fid) + | NullId -> "null" + +let string_of_ptr (t, b, i) = + pp "%s %s %s" (string_of_ty t) (string_of_bid b) + (mapcat ", " string_of_int i) + +let string_of_sval (sv:sval) : string = + match sv with + | VUndef -> "undef" + | VInt x -> Int64.to_string x + | VPtr p -> string_of_ptr p + +let rec string_of_mval (mv:mval) : string = + "[" ^ (mapcat " " string_of_mtree mv) ^ "]" + +and string_of_mtree = function + | MWord sv -> string_of_sval sv + | MStr s -> "\"" ^ s ^ "\"" + | MNode m -> string_of_mval m + + +(* Varieties of undefined behavior. Can be raised by load/store *) +exception OOBIndexDeref (* mem access not in bounds of an array *) +exception NullPtrDeref (* deref Null *) +exception UndefPtrDeref (* deref Undef pointer (from bad GEP) *) +exception IncompatTagDeref (* deref pointer at wrong type (bad bitcast) *) +exception UndefMemDeref (* read uninitialized memory *) +exception UninitMemLoad (* uninitialized memory load *) +exception UseAfterFree (* deref freed stack/heap memory *) + + +(* Arithmetic operations are all signed 64bit 2s compliment (mod In64.max_int) *) +let interp_bop (b:bop) (v1:sval) (v2:sval) : sval = + let i, j = match v1, v2 with + | VInt i, VInt j -> i, j + | _ -> invalid_arg "interp_bop" + in + let open Int64 in + let f = match b with + | Add -> add | Sub -> sub | Mul -> mul + | And -> logand | Or -> logor | Xor -> logxor + | Shl -> fun i j -> shift_left i @@ to_int j + | Lshr -> fun i j -> shift_right_logical i @@ to_int j + | Ashr -> fun i j -> shift_right i @@ to_int j + in VInt (f i j) + +let interp_cnd (c:cnd) (v1:sval) (v2:sval) = + let f = match c with + | Eq -> (=) | Ne -> (<>) | Slt -> (<) + | Sle -> (<=) | Sgt -> (>) | Sge -> (>=) + in + match v1, v2, c with + | VPtr (_,b1,i1), VPtr (_,b2,i2), Eq + | VPtr (_,b1,i1), VPtr (_,b2,i2), Ne -> + VInt (if f (b1,i1) (b2,i2) then 1L else 0L) + | VInt i, VInt j, _ -> + VInt (if f i j then 1L else 0L) + | _ -> invalid_arg "interp_cnd" + +let interp_i1 : sval -> bool = function + | VInt 0L -> false + | VInt 1L -> true + | _ -> invalid_arg "interp_i1" + +let rec interp_operand (nt:tid -> ty) (locs:locals) (ty:ty) (o:operand) : sval = + match ty, o with + | I64, Const i + | I1, Const i -> VInt i + | Ptr ty, Null -> VPtr (ty, NullId, [0]) + | Ptr ty, Gid g -> VPtr (ty, GlobId g, [0]) + | _, Id u -> locs u + | Namedt id, o -> interp_operand nt locs (nt id) o + | _ -> failwith @@ "interp_operand: malformed operand " ^ soo o ^ ":" ^ sot ty + + +(* Some utility functions *) +let update f k v = fun k' -> if k = k' then v else f k' + +let rec is_prefix (l:'a list) (m:'a list) : bool = + match l, m with + | [], _ -> true + | _, [] -> false + | a::l, b::m -> a = b && is_prefix l m + +let replace_assoc (l:('a * 'b) list) (a:'a) (b:'b) : ('a * 'b) list = + let rec loop acc = function + | [] -> List.rev @@ (a,b)::acc + | (a',_)::l' when a = a' -> List.rev_append acc @@ (a,b):: l' + | e::l' -> loop (e::acc) l' + in + loop [] l + +let replace_nth (l:'a list) (n:int) (a:'a) : 'a list = + let rec loop acc n = function + | [] -> raise Not_found + | a'::l' -> if n = 0 then List.rev_append acc (a::l') + else loop (a'::acc) (pred n) l' + in + loop [] n l + + +(* Memory access *) +let rec load_idxs (m:mval) (idxs:idx list) : mtree = + match idxs with + | [] -> MNode m + | i::idxs' -> + let len = List.length m in + if len <= i || i < 0 then raise OOBIndexDeref else + match idxs', List.nth m i with + | [], mt -> mt + | [0], MStr s -> MStr s (* [n x i8]* %p and gep [n x i8]* %p, 0, 0 alias *) + | _, MWord _ -> failwith "load_idxs: attempted to index into word" + | _, MStr _ -> failwith "load_idxs: attempted to index into string" + | _, MNode m' -> load_idxs m' idxs' + +let rec store_idxs (m:mval) (idxs:idx list) (mt:mtree) : mval = + match idxs with + | [] -> [mt] + | i::idxs' -> + let len = List.length m in + if len <= i || i < 0 then raise OOBIndexDeref else + match idxs', List.nth m i with + | [], _ -> replace_nth m i mt + | _, MWord _ -> failwith "store_idxs: attempted to index into word" + | _, MStr _ -> failwith "store_idxs: attempted to index into string" + | _, MNode m' -> replace_nth m i @@ MNode (store_idxs m' idxs' mt) + +let load_bid (c:config) (bid:bid) : mval = + match bid with + | NullId -> raise NullPtrDeref + | HeapId mid -> + (try List.assoc mid c.heap + with Not_found -> raise UseAfterFree) + | GlobId gid -> + (try List.assoc gid c.globals + with Not_found -> failwith "Load: bogus gid") + | StckId fid -> + (try List.assoc fid c.stack + with Not_found -> raise UseAfterFree) + + +let load_ptr (c:config) (_, bid, idxs:ptr) : mtree = + load_idxs (load_bid c bid) idxs + +let store_ptr (c:config) (_, bid, idxs:ptr) (mt:mtree) : config = + let mval = load_bid c bid in + match bid with + | NullId -> raise NullPtrDeref + | HeapId mid -> + let mval' = store_idxs mval idxs mt in + let heap = replace_assoc c.heap mid mval' in + {c with heap} + | GlobId gid -> + let mval' = store_idxs mval idxs mt in + let globals = replace_assoc c.globals gid mval' in + {c with globals} + | StckId fid -> + let frame' = store_idxs mval idxs mt in + let stack = replace_assoc c.stack fid frame' in + {c with stack} + + +(* Tag and GEP implementation *) +let effective_tag (nt:tid -> ty) (tag, _, idxs :ptr) : ty = + let rec loop tag idxs = + match tag, idxs with + | t, [] -> t + | Struct ts, i::idxs' -> if List.length ts <= i + then failwith "effective_tag: index oob of struct" + else loop (List.nth ts i) idxs' + | Array (_, t), _::idxs' -> loop t idxs' (* Don't check if OOB! *) + | Namedt id, _ -> loop (nt id) idxs + | _, _::_ -> failwith "effective_tag: index into non-aggregate" + in + loop tag @@ try List.tl idxs + with Failure _ -> failwith "effective_tag: invalid pointer missing first index" + + +let rec gep_idxs (p:idx list) (idxs:idx list) : idx list = + match p, idxs with + | [], _ | _, [] -> failwith "gep_idxs: invalid indices" + | [i], j::idxs' -> i+j::idxs' + | i::p', _ -> i::gep_idxs p' idxs + + +let legal_gep (nt:tid -> ty) (sty:ty) (tag:ty) : bool = + let rec ptrtoi8 : ty -> ty = function + | Ptr _ -> Ptr I8 + | Struct ts -> Struct (List.map ptrtoi8 ts) + | Array (n, t) -> Array (n, ptrtoi8 t) + | Namedt id -> ptrtoi8 (nt id) + | t -> t + in + let rec flatten_ty : ty -> ty list = function + | Struct ts -> List.(concat @@ map flatten_ty ts) + | t -> [t] + in + is_prefix (flatten_ty @@ ptrtoi8 sty) (flatten_ty @@ ptrtoi8 tag) + +let gep_ptr (nt:tid -> ty) (ot:ty) (p:ptr) (idxs':idx list) : sval = + if not (legal_gep nt ot @@ effective_tag nt p) then VUndef else + match p with + | _t, NullId, _idxs -> VUndef + | t, bid, idxs -> + VPtr (t, bid, gep_idxs idxs idxs') + + +(* LLVMlite reference interpreter *) +let interp_prog {tdecls; gdecls; fdecls; _} (args:string list) : sval = + + let globals = List.map (fun (g,gd) -> g,mval_of_gdecl gd) gdecls in + + let nt (id:tid) : ty = + try List.assoc id tdecls + with Not_found -> failwith @@ "interp_prog: undefined named type " ^ id + in + + let rec effective_type t = + match t with + | Namedt id -> effective_type (nt id) + | _ -> t + in + + let interp_op = interp_operand nt in + + let next_id : unit -> fid = + let c = ref 0 in + fun () -> c := succ !c; !c + in + + (* Global identifiers that will be interpreted as external functions *) + let runtime_fns = [ "ll_puts"; "ll_strcat"; "ll_ltoa" ] + in + + (* External function implementation *) + let runtime_call (t:ty) (fn:gid) (args:sval list) (c:config) : config * sval = + let load_strptr p = match load_ptr c p with + | MStr s -> s + | _ -> failwith "runtime_call: non string-ptr arg" + in + match t, fn, args with + | Void, "ll_puts", [VPtr p] -> + let s = load_strptr p in + print_endline s; + c, VUndef + | Ptr t, "ll_strcat", [VPtr ps1; VPtr ps2] -> + let s1 = load_strptr ps1 in + let s2 = load_strptr ps2 in + let mid = next_id () in + let mv = [MStr (s1 ^ s2)] in + let heap = (mid, mv)::c.heap in + {c with heap}, VPtr (t, HeapId mid, [0]) + | I64, "ll_ltoa", [VInt i; VPtr _dst] -> + let mid = next_id () in + let mv = [MStr (Int64.to_string i)] in + let heap = (mid, mv)::c.heap in + {c with heap}, VPtr (t, HeapId mid, [0]) + | _ -> failwith @@ "runtime_call: invalid call to " ^ fn + in + + + (* Interpret the body of a function *) + let rec interp_cfg (k, blocks:cfg) (locs:locals) (c:config) : config * sval = + match k.insns, k.term with + + | (u, Binop (b, t, o1, o2))::insns, _ -> + let v1 = interp_op locs t o1 in + let v2 = interp_op locs t o2 in + let vr = interp_bop b v1 v2 in + let locs' = update locs u vr in + interp_cfg ({k with insns}, blocks) locs' c + + | (u, Icmp (cnd, t, o1, o2))::insns, _ -> + let v1 = interp_op locs t o1 in + let v2 = interp_op locs t o2 in + let vr = interp_cnd cnd v1 v2 in + let locs' = update locs u vr in + interp_cfg ({k with insns}, blocks) locs' c + + | (u, Alloca ty)::insns, _ -> + begin match c.stack with + | [] -> failwith "stack empty" + | (fid,frame)::stack' -> + let ptr = VPtr (ty, StckId fid, [List.length frame]) in + let stack = (fid, frame @ [MWord VUndef])::stack' in + let locs' = update locs u ptr in + interp_cfg ({k with insns}, blocks) locs' {c with stack} + end + + | (u, Load (Ptr t, o))::insns, _ -> + let mt = match interp_op locs (Ptr t) o with + | VPtr p -> + if effective_type (effective_tag nt p) <> effective_type t + then raise IncompatTagDeref + else load_ptr c p + | VUndef -> raise UndefPtrDeref + | VInt _ -> failwith "non-ptr arg for load" + in + let v = match mt with + | MWord VUndef -> raise UninitMemLoad + | MWord v -> v + | _ -> failwith "load: returned aggregate" + in + let locs' = update locs u v in + interp_cfg ({k with insns}, blocks) locs' c + + | (_, Store (t, os, od))::insns, _ -> + let vs = interp_op locs t os in + let vd = interp_op locs (Ptr t) od in + let c' = match vd with + | VPtr p -> + if effective_type (effective_tag nt p) <> effective_type t + then raise IncompatTagDeref + else store_ptr c p (MWord vs) + | VUndef -> raise UndefPtrDeref + | VInt _ -> failwith "non-vptr arg for load" + in + interp_cfg ({k with insns}, blocks) locs c' + + | (u, Call (t, ofn, ato))::insns, _ -> + let ats, aos = List.split ato in + let ft = Ptr (Fun (ats, t)) in + let g = match interp_op locs ft ofn with + | VPtr (_, GlobId g, [0]) -> g + | _ -> failwith "bad call arg" + in + let args = List.map2 (interp_op locs) ats aos in + let c', r = interp_call t g args c in + let locs' = update locs u r in + interp_cfg ({k with insns}, blocks) locs' c' + + | (u, Bitcast (t1, o, _))::insns, _ -> + let v = interp_op locs t1 o in + let locs' = update locs u v in + interp_cfg ({k with insns}, blocks) locs' c + + | (u, Gep (ty, o, os))::insns, _ -> + let t = dptr tdecls ty in + let idx_of_sval : sval -> idx = function + | VInt i -> Int64.to_int i + | _ -> failwith "idx_of_sval: non-integer value" + in + let vs = List.map (interp_op locs I64) os in + let idxs' = List.map idx_of_sval vs in + let v' = match interp_op locs (Ptr t) o with + | VPtr p -> gep_ptr nt t p idxs' + | VUndef -> VUndef + | VInt _ -> failwith @@ "non-ptr arg for gep" ^ sot t + in + let locs' = update locs u v' in + interp_cfg ({k with insns}, blocks) locs' c + + | [], (_, Ret (_, None)) -> + {c with stack = List.tl c.stack}, VUndef + + | [], (_, Ret (t, Some o)) -> + {c with stack = List.tl c.stack}, interp_op locs t o + + | [], (_, Br l) -> + let k' = List.assoc l blocks in + interp_cfg (k', blocks) locs c + + | [], (_, Cbr (o, l1, l2)) -> + let v = interp_op locs I1 o in + let l' = if interp_i1 v then l1 else l2 in + let k' = List.assoc l' blocks in + interp_cfg (k', blocks) locs c + + | (u,i)::_, _ -> failwith @@ "interp_cfg: invalid instruction \"" + ^ string_of_insn tdecls i ^ "\" at %" ^ u + + and interp_call (ty:ty) (fn:gid) (args:sval list) (c:config) : config * sval = + if List.mem fn runtime_fns + then runtime_call ty fn args c + else + let {f_param; f_cfg; _} = try List.assoc fn fdecls + with Not_found -> failwith @@ "interp_call: undefined function " ^ fn + in + if List.(length f_param <> length args) then + failwith @@ "interp_call: wrong no. arguments for " ^ fn; + let init_locs l = failwith @@ "interp_call: undefined local " ^ l in + let locs = List.fold_left2 update init_locs f_param args in + let stack = (next_id(), [])::c.stack in + interp_cfg f_cfg locs {c with stack} + in + + let mkarg a (p,h) = + let id = next_id () in + VPtr (I8, HeapId id, [0])::p, (id, [MStr a])::h + in + let ptrs, heap = List.fold_right mkarg ("LLINTERP"::args) ([],[]) in + + let narg = List.length args + 1 in + let argc = VInt (Int64.of_int @@ narg) in + let aid = next_id () in + let argv = VPtr (Array (narg, Ptr I8), HeapId aid, [0; 0]) in + let amval = List.map (fun p -> MWord p) ptrs in + let heap = (aid, [MNode amval])::heap in + + let _, r = interp_call I64 "main" [argc; argv] {globals; heap; stack=[]} in + r + + diff --git a/hw5/ll/lllexer.mll b/hw5/lib/ll/lllexer.mll similarity index 91% rename from hw5/ll/lllexer.mll rename to hw5/lib/ll/lllexer.mll index 2fbacba..83a3465 100644 --- a/hw5/ll/lllexer.mll +++ b/hw5/lib/ll/lllexer.mll @@ -1,5 +1,4 @@ -{ open Lexing - open Llparser +{ open Llparser exception SyntaxError of string } @@ -16,7 +15,8 @@ rule token = parse | eof { EOF } | whitespace+ { token lexbuf } | newline+ { token lexbuf } - | "c\"" { read_string (Buffer.create 17) lexbuf } + | "\"" { read_string (Buffer.create 16) lexbuf } + | "c\"" { read_string (Buffer.create 16) lexbuf } | '*' { STAR } | ',' { COMMA } | ':' { COLON } @@ -65,6 +65,8 @@ rule token = parse | "external" { EXTERNAL } | "alloca" { ALLOCA } | "bitcast" { BITCAST } + | "target" { TARGET } + | "triple" { TRIPLE } | '%' ('.' ?) (identifier as i) { UID i } | '@' ('.' ?) (identifier as i) { GID i } | "x" { CROSS } (* for Array types *) @@ -76,6 +78,7 @@ rule token = parse and read_string buf = parse | '\\' "00" '"' { STRING (Buffer.contents buf) } + | '"' { STRING (Buffer.contents buf) } | '\\' { Buffer.add_char buf '\\'; read_string buf lexbuf } | [^ '"' '\\']+ { Buffer.add_string buf (Lexing.lexeme lexbuf) ; read_string buf lexbuf } diff --git a/hw5/ll/llparser.mly b/hw5/lib/ll/llparser.mly similarity index 96% rename from hw5/ll/llparser.mly rename to hw5/lib/ll/llparser.mly index ca28340..4b70a84 100644 --- a/hw5/ll/llparser.mly +++ b/hw5/lib/ll/llparser.mly @@ -56,6 +56,8 @@ %token ALLOCA (* alloca *) %token BITCAST (* bitcast *) %token GEP (* getelementptr *) +%token TARGET (* target *) +%token TRIPLE (* triple *) %token INT (* int64 values *) %token LBL (* labels *) @@ -89,6 +91,11 @@ decls_rev: { { ds with tdecls = t :: ds.tdecls } } | ds=decls_rev e=edecl { { ds with edecls = e :: ds.edecls } } + | ds=decls_rev ttdecl + { ds } + +ttdecl: + TARGET TRIPLE EQUALS STRING {} fdecl: | DEFINE t=ty l=GID LPAREN a=arg_list RPAREN @@ -134,6 +141,8 @@ ty: { t } ty_list_rev: + | (* empty *) + { [] } | t=ty { [t] } | ts=ty_list_rev COMMA t=ty @@ -252,7 +261,7 @@ insn: { (u, Alloca t) } | u=UID EQUALS LOAD ty COMMA t=ty o=operand { (u, Load (t,o)) } - | STORE t1=ty o1=operand COMMA t2=ty o2=operand + | STORE t1=ty o1=operand COMMA _t2=ty o2=operand { (gensym "store", Store (t1,o1,o2)) } | u=UID EQUALS ICMP c=cnd t=ty o1=operand COMMA o2=operand { (u, Icmp (c,t,o1,o2)) } diff --git a/hw5/ll/llruntime.c b/hw5/lib/ll/llruntime.c similarity index 100% rename from hw5/ll/llruntime.c rename to hw5/lib/ll/llruntime.c diff --git a/hw5/ll/llutil.ml b/hw5/lib/ll/llutil.ml similarity index 74% rename from hw5/ll/llutil.ml rename to hw5/lib/ll/llutil.ml index 044d536..c487b9b 100644 --- a/hw5/ll/llutil.ml +++ b/hw5/lib/ll/llutil.ml @@ -20,9 +20,12 @@ let rec string_of_ty : ty -> string = function let sot = string_of_ty -let dptr = function +let rec dptr tdecls = function | Ptr t -> t - | _ -> failwith "PP: expected pointer type" + | Namedt id -> + (try dptr tdecls (List.assoc id tdecls) + with Not_found -> failwith @@ "dptr: undefined named type " ^ id) + | t -> failwith @@ "PP: expected pointer type, got " ^ (sot t) let string_of_operand : operand -> string = function | Null -> "null" @@ -48,11 +51,12 @@ let string_of_gep_index : operand -> string = function | Const i -> "i32 " ^ Int64.to_string i | o -> "i64 " ^ soo o -let string_of_insn : insn -> string = function +let string_of_insn (tdecls:(tid * ty) list) (i:insn) : string = + match i with | Binop (b, t, o1, o2) -> pp "%s %s %s, %s" (string_of_bop b) (sot t) (soo o1) (soo o2) | Alloca t -> pp "alloca %s" (sot t) - | Load (t, o) -> pp "load %s, %s %s" (sot (dptr t)) (sot t) (soo o) + | Load (t, o) -> pp "load %s, %s %s" (sot (dptr tdecls t)) (sot t) (soo o) | Store (t, os, od) -> pp "store %s %s, %s %s" (sot t) (soo os) (sot (Ptr t)) (soo od) | Icmp (c, t, o1, o2) -> pp "icmp %s %s %s, %s" @@ -60,13 +64,13 @@ let string_of_insn : insn -> string = function | Call (t, o, oa) -> pp "call %s %s(%s)" (sot t) (soo o) (mapcat ", " soop oa) | Bitcast (t1, o, t2) -> pp "bitcast %s %s to %s" (sot t1) (soo o) (sot t2) - | Gep (t, o, oi) -> pp "getelementptr %s, %s %s, %s" (sot (dptr t)) (sot t) (soo o) + | Gep (t, o, oi) -> pp "getelementptr %s, %s %s, %s" (sot (dptr tdecls t)) (sot t) (soo o) (mapcat ", " string_of_gep_index oi) -let string_of_named_insn (u,i:uid * insn) : string = +let string_of_named_insn (tdecls:(tid * ty) list) (u,i:uid * insn) : string = match i with - | Store _ | Call (Void, _, _) -> string_of_insn i - | _ -> pp "%%%s = %s" u (string_of_insn i) + | Store _ | Call (Void, _, _) -> string_of_insn tdecls i + | _ -> pp "%%%s = %s" u (string_of_insn tdecls i) let string_of_terminator : terminator -> string = function | Ret (_, None) -> "ret void" @@ -74,26 +78,42 @@ let string_of_terminator : terminator -> string = function | Br l -> pp "br label %%%s" l | Cbr (o, l, m) -> pp "br i1 %s, label %%%s, label %%%s" (soo o) l m -let string_of_block (b:block) : string = - (mapcat "\n" (prefix " " string_of_named_insn) b.insns ^. "\n") +let string_of_block (tdecls:(tid * ty) list) (b:block) : string = + (mapcat "\n" (prefix " " (string_of_named_insn tdecls)) b.insns ^. "\n") ^ (prefix " " string_of_terminator) (snd b.term) -let string_of_cfg (e,bs:cfg) : string = - let string_of_named_block (l,b) = l ^ ":\n" ^ string_of_block b in - string_of_block e ^ "\n" ^. mapcat "\n" string_of_named_block bs +let string_of_cfg (tdecls:(tid * ty) list) (e,bs:cfg) : string = + let string_of_named_block (l,b) = l ^ ":\n" ^ string_of_block tdecls b in + string_of_block tdecls e ^ "\n" ^. mapcat "\n" string_of_named_block bs -let string_of_named_fdecl (g,f:gid * fdecl) : string = +let string_of_named_fdecl (tdecls:(tid * ty) list) (g,f:gid * fdecl) : string = let string_of_arg (t,u) = pp "%s %%%s" (sot t) u in let ts, t = f.f_ty in pp "define %s @%s(%s) {\n%s\n}\n" (sot t) g (mapcat ", " string_of_arg List.(combine ts f.f_param)) - (string_of_cfg f.f_cfg) + (string_of_cfg tdecls f.f_cfg) + + +(* Utility function to escape strings to use \hh encoding for various characters *) +let escape (s:string) : string = + let buf = Buffer.create (String.length s) in + let add_char c = + match c with + | '\n' -> Buffer.add_string buf "\\0A" + | '\t' -> Buffer.add_string buf "\\09" + | '\r' -> Buffer.add_string buf "\\0D" + | '"' -> Buffer.add_string buf "\\22" + | '\\' -> Buffer.add_string buf "\\5C" + | _ -> Buffer.add_char buf c + in + String.iter add_char s; + Buffer.contents buf let rec string_of_ginit : ginit -> string = function | GNull -> "null" | GGid g -> pp "@%s" g | GInt i -> Int64.to_string i - | GString s -> pp "c\"%s\\00\"" s + | GString s -> pp "c\"%s\\00\"" (escape s) | GArray gis -> pp "[ %s ]" (mapcat ", " string_of_gdecl gis) | GStruct gis -> pp "{ %s }" (mapcat ", " string_of_gdecl gis) | GBitcast (t1,g,t2) -> pp "bitcast (%s %s to %s)" (sot t1) (string_of_ginit g) (sot t2) @@ -116,8 +136,8 @@ let string_of_named_edecl (g,t:gid * ty) : string = let string_of_prog (p:prog) : string = (mapcat "\n" string_of_named_tdecl p.tdecls ^. "\n\n") ^ (mapcat "\n" string_of_named_gdecl p.gdecls ^. "\n\n") - ^ (mapcat "\n" string_of_named_fdecl p.fdecls ^. "\n\n") - ^ (mapcat "\n" string_of_named_edecl p.edecls) + ^ (mapcat "\n" (string_of_named_fdecl p.tdecls) p.fdecls ^. "\n\n") + ^ (mapcat "\n" string_of_named_edecl p.edecls) ^. "\n" (* comparison for testing ----------------------------------------------------- *) @@ -129,7 +149,7 @@ let compare_block (b:block) (c:block) : int = | Call (Void, _, _) -> "", i | _ -> u, i in - let del_term (u,t) = ("", t) + let del_term (_u,t) = ("", t) in Stdlib.compare {insns=List.map del_dummy b.insns; term=del_term b.term} diff --git a/hw5/lib/util/assert.ml b/hw5/lib/util/assert.ml new file mode 100644 index 0000000..8e326a0 --- /dev/null +++ b/hw5/lib/util/assert.ml @@ -0,0 +1,195 @@ +(* CIS341 Assertion Testing and Grading Infrastructure *) +(* Author: Steve Zdancewic *) + +(* Do NOT modify this file -- we will overwrite it *) +(* with our own version when testing your code. *) + +(* An assertion is just a unit->unit function that either *) +(* succeeds silently or throws an Failure exception. *) +type assertion = unit -> unit + +type 'a test = + | GradedTest of string * int * (string * 'a) list + | Test of string * (string * 'a) list + +type suite = assertion test list + +(**************) +(* Assertions *) + +let assert_eq v1 v2 : assertion = + fun () -> if v1 <> v2 then failwith "not equal" else () + + +let assert_eqf f v2 : assertion = + fun () -> if f () <> v2 then failwith "not equal" else () + + +let assert_eqfs f v2 : assertion = + fun () -> + let s1 = f () in + if s1 <> v2 + then failwith @@ Printf.sprintf "not equal\n\texpected:%s\n\tgot:%s\n" v2 s1 + else () + + +let assert_fail : assertion = fun () -> failwith "assert fail" + +exception Timeout + +let timeout_assert (time : int) (a : assertion) : assertion = + fun () -> + let handler = Sys.Signal_handle (fun _ -> raise Timeout) in + let old = Sys.signal Sys.sigalrm handler in + let reset_sigalrm () = Sys.set_signal Sys.sigalrm old in + ignore (Unix.alarm time) ; + try + a () ; + reset_sigalrm () + with + | Timeout -> + reset_sigalrm () ; + failwith @@ Printf.sprintf "Timed out after %d seconds" time + | exc -> + reset_sigalrm () ; + raise exc + + +let timeout_test (time : int) (t : assertion test) : assertion test = + let map_timeout l = List.map (fun (i, a) -> (i, timeout_assert time a)) l in + match t with + | GradedTest (s, i, ls) -> + GradedTest (s, i, map_timeout ls) + | Test (s, ls) -> + Test (s, map_timeout ls) + + +let timeout_suite (time : int) (s : suite) : suite = + List.map (timeout_test time) s + + +(***************************) +(* Generating Test Results *) + +type result = + | Pass + | Fail of string + +type outcome = result test list + +let run_assertion (f : assertion) : result = + try + f () ; + Pass + with + | Failure m -> + Fail m + | e -> + Fail ("test threw exception: " ^ Printexc.to_string e) + + +let run_test (t : assertion test) : result test = + let run_case (cn, f) = (cn, run_assertion f) in + match t with + | GradedTest (n, s, cases) -> + Printf.eprintf "Running test %s\n%!" n ; + GradedTest (n, s, List.map run_case cases) + | Test (n, cases) -> + Printf.eprintf "Running test %s\n%!" n ; + Test (n, List.map run_case cases) + + +let run_suite (s : suite) : outcome = List.map run_test s + +(***********************) +(* Reporting functions *) + +let result_test_to_string (name_pts : string) (r : result test) : string = + let string_of_case (name, res) = + match res with + | Pass -> + "passed - " ^ name + | Fail msg -> + "FAILED - " ^ name ^ ": " ^ msg + in + match r with + | GradedTest (_, _, cases) | Test (_, cases) -> + name_pts + ^ List.fold_left + (fun rest case -> rest ^ "\n" ^ string_of_case case) + "" + cases + + +(* Number of digits of precision for a float x. Argument p is the number of decimal places desired (must be at least 1) *) +let prec_digits p x = (int_of_float @@ floor @@ log10 x) + (1 + p) + +(* returns (name_pts, passed, failed, total, points_earned, max_given, max_hidden) *) +let get_results (t : result test) = + let num_passed cases = + List.fold_left + (fun cnt (_, r) -> match r with Pass -> cnt + 1 | _ -> cnt) + 0 + cases + in + let num_failed cases = + List.fold_left + (fun cnt (_, r) -> match r with Fail _ -> cnt + 1 | _ -> cnt) + 0 + cases + in + match t with + | GradedTest (name, pts, cases) -> + let passed = num_passed cases in + let failed = num_failed cases in + let total = List.length cases in + if total > 0 + then + let points_earned = ((float_of_int passed) /. (float_of_int total)) *. (float_of_int pts) in + let name_pts = + Printf.sprintf "%s (%1.*g/%d points = %d/%d tests)" name (prec_digits 1 points_earned) points_earned pts passed total + in + (name_pts, passed, failed, total, points_earned, pts, 0) + else + let name_pts = Printf.sprintf "%s (?/%d points)" name pts in + (name_pts, passed, failed, total, 0.0, 0, pts) + | Test (name, cases) -> + let total = List.length cases in + let passed = num_passed cases in + let failed = num_failed cases in + (name, passed, failed, total, 0.0, 0, 0) + + +let outcome_to_string (o : outcome) : string = + let sep = "\n---------------------------------------------------\n" in + let helper (passed, failed, total, pts, maxg, maxh, str) (t : result test) = + let name_pts, p, f, tot, s, mg, mh = get_results t in + ( passed + p + , failed + f + , total + tot + , s +. pts + , maxg + mg + , maxh + mh + , str + ^ "\n" + ^ + if f > 0 + then result_test_to_string name_pts t + else if tot > 0 + then name_pts ^ ":\n OK" + else name_pts ^ ":\n Hidden" ) + in + let p, f, tot, pts, maxg, maxh, str = + List.fold_left helper (0, 0, 0, 0.0, 0, 0, "") o + in + str + ^ sep + ^ Printf.sprintf + "Passed: %d/%d\n\ + Failed: %d/%d\n\ + Score: %1.1f/%d (given)\n\ + \ ?/%d (hidden)" + p tot + f tot + pts maxg + maxh diff --git a/hw5/util/assert.mli b/hw5/lib/util/assert.mli similarity index 77% rename from hw5/util/assert.mli rename to hw5/lib/util/assert.mli index 6b53684..9dfa6d0 100644 --- a/hw5/util/assert.mli +++ b/hw5/lib/util/assert.mli @@ -8,44 +8,50 @@ exception Timeout (* An assertion is just a unit->unit function that either *) (* succeeds silently or throws an Failure exception. *) -type assertion = (unit -> unit) +type assertion = unit -> unit -type 'a test = +type 'a test = | GradedTest of string * int * (string * 'a) list | Test of string * (string * 'a) list -type suite = (assertion test) list - +type suite = assertion test list (**************) (* Assertions *) -val assert_eq : 'a -> 'a -> assertion +val assert_eq : 'a -> 'a -> assertion + val assert_eqf : (unit -> 'a) -> 'a -> assertion + val assert_eqfs : (unit -> string) -> string -> assertion -val assert_fail : assertion + +val assert_fail : assertion val timeout_assert : int -> assertion -> assertion + val timeout_test : int -> assertion test -> assertion test + val timeout_suite : int -> suite -> suite (***************************) (* Generating Test Results *) -type result = - | Pass +type result = + | Pass | Fail of string -type outcome = (result test) list +type outcome = result test list val run_assertion : assertion -> result + val run_test : assertion test -> result test + val run_suite : suite -> outcome (***********************) (* Reporting functions *) -val result_test_to_string : string -> result test -> string +val result_test_to_string : string -> result test -> string (* val get_results result test -> (string * int * int * int * float * int * int) *) -val outcome_to_string :outcome -> string +val outcome_to_string : outcome -> string diff --git a/hw5/lib/util/dune b/hw5/lib/util/dune new file mode 100644 index 0000000..aa0f522 --- /dev/null +++ b/hw5/lib/util/dune @@ -0,0 +1,3 @@ +(library + (name util) + (libraries str unix)) \ No newline at end of file diff --git a/hw5/lib/util/platform.ml b/hw5/lib/util/platform.ml new file mode 100644 index 0000000..13a96a0 --- /dev/null +++ b/hw5/lib/util/platform.ml @@ -0,0 +1,237 @@ +(* -------------------------------------------------------------------------- *) +(** Assembling and linking for X86. Depends on the underlying OS platform *) + +open Printf +open Unix + +exception PlatformError of string * string + +(* paths -------------------------------------------------------------------- *) +let path_sep = "/" + +let bin_path = "./bin" + +let dot_path = "./" + +let executable_name = ref "a.out" + +let output_path = ref "output" + +let libs = ref [] + +let lib_paths = ref [] + +let lib_search_paths = ref [] + +let include_paths = ref [] + +(* unix utility scripts ----------------------------------------------------- *) +let pp_cmd = ref "cpp -E " + +let rm_cmd = ref "rm -rf " + +(* -------------------------------------------------------------------------- *) +(* Platform specific configuration: Unix/Linux vs. Mac OS X *) + +let os = + let ic = Unix.open_process_in "uname -s" in + let uname = input_line ic in + let () = close_in ic in + uname + +let cpu = + let ic = Unix.open_process_in "uname -m" in + let cpuname = input_line ic in + let () = close_in ic in + cpuname + +(* One of "Darwin" or "Linux" *) + +let linux = ref false + +let mangle name = if !linux then name else "_" ^ name + +let osx_target_triple = "x86_64-apple-macosx10.13.0" + +let linux_target_triple = "x86_64-unknown-linux" + +let target_triple = ref osx_target_triple + +let platform_flags = ref "" + +(* Set the link commands properly, ensure output directory exists *) +let configure_os () = + if os = "Linux" + then ( + linux := true ; + target_triple := linux_target_triple ; + platform_flags := "" ) + else if os = "Darwin" + then ( + linux := false ; + target_triple := osx_target_triple ; + platform_flags := "-fno-asynchronous-unwind-tables -mstackrealign" ) + else failwith @@ "Unsupported OS detected: " ^ os + + +(* verbose compiler output -------------------------------------------------- *) +let verbose = ref false + +let verb msg = + if !verbose + then ( + print_string msg ; + flush Stdlib.stdout ) + + +let verb_os () = + verb + @@ Printf.sprintf + "* PLATFORM: %s TRIPLE: %s FLAGS %s\n" + os + !target_triple + !platform_flags + + +let enable_verbose () = + verbose := true ; + verb_os () + + +(* create the output directory, which is assumed to exist *) +let create_output_dir () = + try ignore (stat !output_path) with + | Unix_error (ENOENT, _, _) -> + verb @@ Printf.sprintf "creating output directory: %s\n" !output_path ; + mkdir !output_path 0o755 + + +(* clang invocation stuff --------------------------------------------------- *) +let common_flags = "-Wno-override-module" + +let link_flags = "-Wno-unused-command-line-argument -mstackrealign" + +let clang_ll_mode = "-S" + +let as_mode = "-c" + +let rosetta_prefix = "arch -x86_64 " + +let prefix = if cpu = "arm64" then rosetta_prefix else "" + +let opt_level = ref "-O1 -Wall" + +let clang args = Printf.sprintf "%sclang %s -o " prefix (String.concat " " args) + +let clang_cmd () = + clang [ clang_ll_mode; !opt_level; common_flags; !platform_flags ] + + +let as_cmd () = clang [ as_mode; !opt_level; common_flags; !platform_flags ] + +let link_cmd () = clang [ common_flags; !opt_level; !platform_flags; link_flags ] + +(* filename munging --------------------------------------------------------- *) +let path_to_basename_ext (path : string) : string * string = + (* The path is of the form ... "foo/bar/baz/.ext" *) + let paths = Str.split (Str.regexp_string path_sep) path in + let _ = + if List.length paths = 0 then failwith @@ sprintf "bad path: %s" path + in + let filename = List.hd (List.rev paths) in + match Str.split (Str.regexp_string ".") filename with + | [ root ] -> + (root, "") + | [ root; ext ] -> + (root, ext) + | _ -> + failwith @@ sprintf "bad filename: %s" filename + + +(* compilation and shell commands-------------------------------------------- *) + +(* Platform independent shell command *) +let sh (cmd : string) (ret : string -> int -> 'a) : 'a = + verb (sprintf "* %s\n" cmd) ; + match system cmd with + | WEXITED i -> + ret cmd i + | WSIGNALED i -> + raise (PlatformError (cmd, sprintf "Signaled with %d." i)) + | WSTOPPED i -> + raise (PlatformError (cmd, sprintf "Stopped with %d." i)) + +(* Platform independent shell command with a timeout (in seconds) *) +let timeout_sh (time: int)(cmd : string) (ret : string -> int -> 'a) : 'a = + let timeout_cmd = sprintf "%s/timeout3 -t %d %s" bin_path time cmd in + verb (sprintf "* %s\n" timeout_cmd) ; + match system timeout_cmd with + | WEXITED i -> + ret cmd i + | WSIGNALED i -> + if i == Sys.sigterm + then raise (PlatformError (cmd, sprintf "Timed-out after %d s" time)) + else raise (PlatformError (cmd, sprintf "Signaled with %d." i)) + | WSTOPPED i -> + raise (PlatformError (cmd, sprintf "Stopped with %d." i)) + + +(* Generate a file name that does not already exist. + basedir includes the path separator +*) +let gen_name (basedir : string) (basen : string) (baseext : string) : string = + let rec nocollide ofs = + let nfn = + sprintf + "%s/%s%s%s" + basedir + basen + (if ofs = 0 then "" else "_" ^ string_of_int ofs) + baseext + in + try + ignore (stat nfn) ; + nocollide (ofs + 1) + with + | Unix_error (ENOENT, _, _) -> + nfn + in + nocollide 0 + + +let raise_error cmd i = + if i <> 0 then raise (PlatformError (cmd, sprintf "Exited with status %d." i)) + + +let ignore_error _ _ = () + +let preprocess (dot_oat : string) (dot_i : string) : unit = + sh + (sprintf + "%s%s %s %s" + !pp_cmd + (List.fold_left (fun s i -> s ^ " -I" ^ i) "" !include_paths) + dot_oat + dot_i) + raise_error + + +let clang_compile (dot_ll : string) (dot_s : string) : unit = + sh (sprintf "%s%s %s" (clang_cmd ()) dot_s dot_ll) raise_error + + +let assemble (dot_s : string) (dot_o : string) : unit = + sh (sprintf "%s%s %s" (as_cmd ()) dot_o dot_s) raise_error + + +let link (mods : string list) (out_fn : string) : unit = + sh + (sprintf + "%s%s %s %s %s %s" + (link_cmd ()) + out_fn + (String.concat " " (mods @ !lib_paths)) + (List.fold_left (fun s i -> s ^ " -L" ^ i) "" !lib_search_paths) + (List.fold_left (fun s i -> s ^ " -I" ^ i) "" !include_paths) + (List.fold_left (fun s l -> s ^ " -l" ^ l) "" !libs)) + raise_error diff --git a/hw5/lib/util/range.ml b/hw5/lib/util/range.ml new file mode 100644 index 0000000..9a78d1a --- /dev/null +++ b/hw5/lib/util/range.ml @@ -0,0 +1,56 @@ +open Lexing + +type pos = int * int (* Line number and column *) + +type t = string * pos * pos + +let line_of_pos (l, _) = l + +let col_of_pos (_, c) = c + +let mk_pos line col = (line, col) + +let file_of_range (f, _, _) = f + +let start_of_range (_, s, _) = s + +let end_of_range (_, _, e) = e + +let mk_range f s e = (f, s, e) + +let valid_pos (l, c) = l >= 0 && c >= 0 + +let merge_range ((f, s1, e1) as r1) ((f', s2, e2) as r2) = + if f <> f' + then + failwith + @@ Printf.sprintf "merge_range called on different files: %s and %s" f f' + else if not (valid_pos s1) + then r2 + else if not (valid_pos s2) + then r1 + else mk_range f (min s1 s2) (max e1 e2) + + +let string_of_range (f, (sl, sc), (el, ec)) = + Printf.sprintf "%s:[%d.%d-%d.%d]" f sl sc el ec + + +let ml_string_of_range (f, (sl, sc), (el, ec)) = + Printf.sprintf "(\"%s\", (%d, %d), (%d, %d))" f sl sc el ec + + +let norange = ("__internal", (0, 0), (0, 0)) + +(* Creates a Range.pos from the Lexing.position data *) +let pos_of_lexpos (p : position) : pos = + mk_pos p.pos_lnum (p.pos_cnum - p.pos_bol) + + +let mk_lex_range (p1 : position) (p2 : position) : t = + mk_range p1.pos_fname (pos_of_lexpos p1) (pos_of_lexpos p2) + + +(* Expose the lexer state as a Range.t value *) +let lex_range lexbuf : t = + mk_lex_range (lexeme_start_p lexbuf) (lexeme_end_p lexbuf) diff --git a/hw5/util/range.mli b/hw5/lib/util/range.mli similarity index 92% rename from hw5/util/range.mli rename to hw5/lib/util/range.mli index c14f54f..9603713 100644 --- a/hw5/util/range.mli +++ b/hw5/lib/util/range.mli @@ -46,8 +46,8 @@ val ml_string_of_range : t -> string (* use to tag generated AST nodes where range does not apply *) val norange : t -val pos_of_lexpos : Lexing.position -> pos +val pos_of_lexpos : Lexing.position -> pos -val mk_lex_range : Lexing.position -> Lexing.position -> t +val mk_lex_range : Lexing.position -> Lexing.position -> t val lex_range : Lexing.lexbuf -> t diff --git a/hw5/lib/x86/dune b/hw5/lib/x86/dune new file mode 100644 index 0000000..abab108 --- /dev/null +++ b/hw5/lib/x86/dune @@ -0,0 +1,3 @@ +(library + (name x86) + (modules x86)) diff --git a/hw5/x86/x86.ml b/hw5/lib/x86/x86.ml similarity index 95% rename from hw5/x86/x86.ml rename to hw5/lib/x86/x86.ml index 802ee18..514a5c5 100644 --- a/hw5/x86/x86.ml +++ b/hw5/lib/x86/x86.ml @@ -56,13 +56,13 @@ type prog = elem list (* Provide some syntactic sugar for writing x86 code in OCaml files. *) module Asm = struct - let (~$) i = Imm (Lit (Int64.of_int i)) (* int64 constants *) + let (~$) i = Imm (Lit (Int64.of_int i)) (* int64 constants *) let (~$$) l = Imm (Lbl l) (* label constants *) - let (~%) r = Reg r (* registers *) + let (~%) r = Reg r (* registers *) (* helper functions for building blocks of data or code *) - let data l ds = { lbl = l; global = true; asm = Data ds } - let text l is = { lbl = l; global = false; asm = Text is } + let data l ds = { lbl = l; global = true; asm = Data ds } + let text l is = { lbl = l; global = false; asm = Text is } let gtext l is = { lbl = l; global = true; asm = Text is } end @@ -127,7 +127,7 @@ let string_of_opcode : opcode -> string = function let map_concat s f l = String.concat s @@ List.map f l let string_of_shift op = function - | [ Imm i ; dst ] as args -> + | [ Imm _i ; _dst ] as args -> "\t" ^ string_of_opcode op ^ "\t" ^ map_concat ", " string_of_operand args | [ Reg Rcx ; dst ] -> Printf.sprintf "\t%s\t%%cl, %s" (string_of_opcode op) (string_of_operand dst) diff --git a/hw5/oatprograms/bubble_sort.oat b/hw5/oatprograms/bubble_sort.oat deleted file mode 100644 index 1843ca8..0000000 --- a/hw5/oatprograms/bubble_sort.oat +++ /dev/null @@ -1,30 +0,0 @@ -void bubble_sort(int[] arr, int len) { - var swapped = true; - while(swapped) { - swapped = false; - for (var i = 0; i < len-1; i = i+1;) { - if (arr[i] > arr[i+1]) { - var temp = arr[i]; - arr[i] = arr[i+1]; - arr[i+1] = temp; - swapped = true; - } - } - } - return; -} - -int program (int argc, string[] argv) { - var arr = new int[][10]{i -> new int[10]{j-> 10*i-j}}; - var val = 0; - for (var i = 0; i < 10; i = i+1;) { - bubble_sort(arr[i], 10); - val = val + arr[i][i]; - } - - if (val == 405) { - return 1; - } else { - return 0; - } -} diff --git a/hw5/oatprograms/determinant_size2.oat b/hw5/oatprograms/determinant_size2.oat deleted file mode 100644 index b6733d9..0000000 --- a/hw5/oatprograms/determinant_size2.oat +++ /dev/null @@ -1,31 +0,0 @@ -int compute_determinant(int[][] matrix, int n) { - var sum = 0; - var multiplier = -1; - if (n == 1) { - sum = matrix[0][0]; - } - else { - for (var k = 0; k < n; k = k+1;) { - var len = n-1; - var b=new int[][len]{i-> new int[len]{j -> 1}}; - for (var l = 0; l < k; l=l+1;) { - for (var m = 0; m < n-1; m=m+1;) { - b[m][l] = matrix[m+1][l]; - } - } - for (var o = k; o < n-1; o=o+1;) { - for (var p = 0; p < n-1; p=p+1;) { - b[p][o] = matrix[p+1][o+1]; - } - } - multiplier = multiplier * -1; - sum = sum + multiplier * matrix[0][k] * compute_determinant(b, n-1); - } - } - return sum; -} - -int program (int argc, string[] argv) { - var matrix = new int[][]{new int[]{20,2},new int[]{3,5}}; - return compute_determinant(matrix, 2); -} diff --git a/hw5/oatprograms/easy_p5.oat b/hw5/oatprograms/easy_p5.oat deleted file mode 100644 index 1c9abf6..0000000 --- a/hw5/oatprograms/easy_p5.oat +++ /dev/null @@ -1,14 +0,0 @@ -global i = 19; -global b1 = true; -global b2 = false; -global str = "This is a string!"; -global arr1 = int[]{0,1,2}; -global arr2 = int[][]{ int[]{10,11}, int[]{20,21}, int[]{30,31}}; -global arr3 = string[]{"String1", "String2", "String3"}; - -global arr4 = string[][] - { - string[]{"String00","String01"}, - string[]{"String10","String11"}, - string[]{"String20","String21"} - }; diff --git a/hw5/oatprograms/run15.oat b/hw5/oatprograms/run15.oat deleted file mode 100644 index 9d96465..0000000 --- a/hw5/oatprograms/run15.oat +++ /dev/null @@ -1,15 +0,0 @@ -int f(int[][] a) { - return a[1][1]; -} - -int g(int x) { - var arr = new int[][3]{i-> new int[3]{j -> x}}; - return arr[1][1]; -} - -int program (int argc, string[] argv) { - var a = new int[][3]{i -> new int[3]{j -> j}}; - var arr = new int[][4]{i -> new int[5]{j -> i*j }}; - var arr0 = new int[][3]{i -> new int[3]{j -> i*j}}; - return arr[3][4] + a[1][2] + f(arr0) + g(4); -} diff --git a/hw5/oatprograms/run16.oat b/hw5/oatprograms/run16.oat deleted file mode 100644 index 9c0049b..0000000 --- a/hw5/oatprograms/run16.oat +++ /dev/null @@ -1,6 +0,0 @@ -int program (int argc, string[] argv) { - var x = 10; - var a = new int[][3]{i -> new int[3]{j -> x+i+j}}; - var b = a; - return b[2][1]; -} diff --git a/hw5/oatprograms/run17.oat b/hw5/oatprograms/run17.oat deleted file mode 100644 index 1a5ee03..0000000 --- a/hw5/oatprograms/run17.oat +++ /dev/null @@ -1,12 +0,0 @@ -int program (int argc, string[] argv) { - var x = 10; - var a = new int[][3]; - for (var i = 0; i<3; i = i+1;) { - a[i] = new int[3]; - for (var j = 0; j<3; j=j+1;) { - a[i][j] = x+i+j; - } - } - var b = a; - return b[2][2]; -} diff --git a/hw5/oatprograms/run42.oat b/hw5/oatprograms/run42.oat deleted file mode 100644 index b1164ce..0000000 --- a/hw5/oatprograms/run42.oat +++ /dev/null @@ -1,16 +0,0 @@ -int program(int argc, string[] argv) { - var a1=new int[][3]{i->new int[1]{j->0}}; - var a2=new int[][3]{i->new int[1]{j->0}}; - var a3=new int[][3]{i->new int[1]{j->0}}; - var a4=new int[][3]{i->new int[1]{j->0}}; - var a5=new int[3]{i->i}; - a2[0] = a5; - a2[0][0] = 2; - a1 = a2; - a3 = a1; - a1 = a4; - a2 = a3; - a4 = a2; - a3 = a4; - return a3[0][0]; -} diff --git a/hw5/studenttests.ml b/hw5/studenttests.ml deleted file mode 100644 index 34e1771..0000000 --- a/hw5/studenttests.ml +++ /dev/null @@ -1,10 +0,0 @@ -open Assert - -(* These tests are provided by you -- they will be graded manually *) - -(* You should also add additional test cases here to help you *) -(* debug your program. *) - -let provided_tests : suite = [ - -] diff --git a/hw5/submit_zip_contents.txt b/hw5/submit_zip_contents.txt new file mode 100644 index 0000000..d93c577 --- /dev/null +++ b/hw5/submit_zip_contents.txt @@ -0,0 +1,3 @@ +bin/frontend.ml +bin/typechecker.ml + diff --git a/hw5/test/dune b/hw5/test/dune new file mode 100644 index 0000000..d735328 --- /dev/null +++ b/hw5/test/dune @@ -0,0 +1,22 @@ +(env + (dev + (flags + (:standard -g -w "+a-4-7-9-26-27-29-30-32..42-44-45-48-50-60-66..70") + ))) + +(library + (name testlib) + (modules testlib) + (libraries util x86 ll oat)) + +(library + (name studenttests) + (modules studenttests) + (libraries testlib util x86 ll oat)) + +(library + (name gradedtests) + (modules gradedtests + ; + ) + (libraries testlib util x86 ll oat)) diff --git a/hw5/test/gradedtests.ml b/hw5/test/gradedtests.ml new file mode 100644 index 0000000..b2addd3 --- /dev/null +++ b/hw5/test/gradedtests.ml @@ -0,0 +1,404 @@ +open Testlib +open Util.Assert +open X86 +open Ll +module Driver = Oat.Driver +module Backend = Oat.Backend +module Typechecker = Oat.Typechecker +module Frontend = Oat.Frontend +module Tctxt = Oat.Tctxt +open Backend +open Driver + +(* 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 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 = [ + ("hw4programs/easyrun1.oat", "", "17"); + ("hw4programs/easyrun2.oat", "", "35"); + ("hw4programs/easyrun3.oat", "", "73"); + ("hw4programs/easyrun4.oat", "", "6"); + ("hw4programs/easyrun5.oat", "", "212"); + ("hw4programs/easyrun6.oat", "", "9"); + ("hw4programs/easyrun7.oat", "", "23"); + ("hw4programs/easyrun8.oat", "", "160"); + ("hw4programs/easyrun9.oat", "", "236"); +] + +let hw4_globals_tests = [ + ("hw4programs/globals1.oat", "", "42"); + ("hw4programs/globals2.oat", "", "17"); + ("hw4programs/globals3.oat", "", "17"); + ("hw4programs/globals4.oat", "", "5"); + ("hw4programs/globals5.oat", "", "17"); + ("hw4programs/globals6.oat", "", "15"); + ("hw4programs/globals7.oat", "", "3"); +] + +let hw4_path_tests = [ + ("hw4programs/path1.oat", "", "17"); + ("hw4programs/path2.oat", "", "35"); + ("hw4programs/path3.oat", "", "3"); + ("hw4programs/arrayargs1.oat", "", "17"); + ("hw4programs/arrayargs2.oat", "", "17"); + ("hw4programs/arrayargs3.oat", "", "34"); +] + +let hw4_easy_tests = [ + ("hw4programs/run26.oat", "", "0"); + ("hw4programs/run27.oat", "", "99"); + ("hw4programs/run28.oat", "", "18"); + ("hw4programs/run29.oat", "", "1"); + ("hw4programs/run30.oat", "", "9"); + ("hw4programs/run31.oat", "", "9"); + ("hw4programs/run13.oat", "", "1"); + ("hw4programs/run32.oat", "", "33"); + ("hw4programs/run21.oat", "", "99"); + ("hw4programs/run33.oat", "", "1"); + ("hw4programs/run34.oat", "", "66"); + ("hw4programs/run38.oat", "", "31"); + ("hw4programs/run39.oat", "a", "2"); + ("hw4programs/run40.oat", "", "8"); + ("hw4programs/run41.oat", "", "3"); + ("hw4programs/run42.oat", "", "2"); + ("hw4programs/run49.oat", "", "abc0"); + ("hw4programs/run50.oat", "", "abcde0"); + ("hw4programs/run60.oat", "", "85"); + ("hw4programs/run61.oat", "", "3410"); +] + +let hw4_medium_tests = [ + ("hw4programs/fact.oat", "", "1200"); + ("hw4programs/run1.oat", "", "153"); + ("hw4programs/run2.oat", "", "6"); + ("hw4programs/run8.oat", "", "2"); + ("hw4programs/run9.oat", "", "4"); + ("hw4programs/run10.oat", "", "5"); + ("hw4programs/run11.oat", "", "7"); + ("hw4programs/run14.oat", "", "16"); + ("hw4programs/run15.oat", "", "19"); + ("hw4programs/run16.oat", "", "13"); + ("hw4programs/run22.oat", "", "abc0"); + ("hw4programs/run23.oat", "", "1230"); + ("hw4programs/run25.oat", "", "nnn0"); + ("hw4programs/run46.oat", "", "420"); + ("hw4programs/run47.oat", "", "3"); + ("hw4programs/run48.oat", "", "11"); + ("hw4programs/lib4.oat", "", "53220"); + ("hw4programs/lib5.oat", "", "20"); + ("hw4programs/lib6.oat", "", "56553"); + ("hw4programs/lib7.oat", "", "53"); + ("hw4programs/lib8.oat", "", "Hello world!0"); + ("hw4programs/lib9.oat", "a b c d", "abcd5"); + ("hw4programs/lib11.oat", "", "45"); + ("hw4programs/lib14.oat", "", "~}|{zyxwvu0"); + ("hw4programs/lib15.oat", "123456789", "456780"); +] + +let hw4_hard_tests = [ +("hw4programs/fac.oat", "", "120"); +("hw4programs/qsort.oat", "", "kpyf{shomfhkmopsy{255"); +("hw4programs/bsort.oat", "", "y}xotnuw notuwxy}255"); +("hw4programs/msort.oat", "", "~}|{zyxwvu uvwxyz{|}~ 0"); +("hw4programs/msort2.oat", "", "~}|{zyxwvu uvwxyz{|}~ 0"); +("hw4programs/selectionsort.oat", "", "01253065992000"); +("hw4programs/matrixmult.oat", "", "19 16 13 23 \t5 6 7 6 \t19 16 13 23 \t5 6 7 6 \t0"); +] + +let hw4_old_student_tests = [ + ("hw4programs/binary_search.oat", "", "Correct!0") + ; ("hw4programs/xor_shift.oat", "", "838867572\n22817190600") + ; ("hw4programs/sieve.oat", "", "25") + ; ("hw4programs/count_sort.oat", "", "AFHZAAEYC\nAAACEFHYZ0") + ; ("hw4programs/fibo.oat", "", "0") + ; ("hw4programs/heap.oat", "", "1") + ; ("hw4programs/binary_gcd.oat", "", "3") + ; ("hw4programs/lfsr.oat", "", "TFTF FFTT0") + ; ("hw4programs/gnomesort.oat", "", "01253065992000") + ; ("hw4programs/josh_joyce_test.oat", "", "0") + ; ("hw4programs/gcd.oat", "", "16") + ; ("hw4programs/lcs.oat", "", "OAT0") + ; ("hw4programs/insertion_sort.oat", "", "42") + ; ("hw4programs/maxsubsequence.oat", "", "107") +] + +let hw4_type_error_tests = [ + "hw4programs/run3.oat" +; "hw4programs/run5.oat" +; "hw4programs/run35.oat" +; "hw4programs/run43.oat" +; "hw4programs/run44.oat" +; "hw4programs/run45.oat" +] + + +let typecheck_equality_tests = [ + "hw5programs/tc_eq1.oat" + ; "hw5programs/tc_eq2.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_array3.oat"; + "hw5programs/tc_error_array4.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_function_no_shadow.oat"; + "hw5programs/tc_correct_null.oat"; + ] + +let typecheck_correct_other_tests = + [ "hw5programs/tc_correct_array.oat"; + "hw5programs/tc_correct_array2.oat"; + "hw5programs/tc_correct_array3.oat"; + "hw5programs/tc_correct_call.oat"; + "hw5programs/tc_correct_fptr.oat"; + "hw5programs/tc_correct_global_fptr_scope.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"; + "hw5programs/tc_struct_null_field.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 new_tests = [ + ("hw5programs/ifq1.oat", "", "4"); + ("hw5programs/ifq2.oat", "", "5"); + ("hw5programs/ifq3.oat", "", "6"); + ("hw5programs/ifq4.oat", "", "4"); + ("hw5programs/ifq5.oat", "", "4"); + ("hw5programs/run44fixed.oat", "", "hello0"); + ("hw5programs/length1.oat", "", "5"); + ("hw5programs/compile_array_init.oat", "", "2"); + ("hw5programs/array_oob.oat", "", "Out of bounds index 3 for array length 30001"); + ("hw5programs/conquest.oat", "", "My name is Jeff...\nCharizard is the BEST Pokemon ever!!!11"); +] + +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" +; "hw4programs/tc_ok1.oat" +; "hw4programs/tc_ok2.oat" +; "hw4programs/tc_ok4.oat" +; "hw4programs/tc_ok5.oat" +; "hw4programs/tc_ok6.oat" +; "hw4programs/tc_ok7.oat" +; "hw4programs/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", 1, 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 equality tests", 4, typecheck_file_correct typecheck_equality_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 hw5_tests : suite = [ + GradedTest("tc ok tests", 8, executed_tc_ok_file tc_ok_tests) +; GradedTest("new tests", 8, executed_oat_file new_tests) +; GradedTest("struct tests", 8, executed_oat_file struct_tests) +; GradedTest("fptr tests", 2, executed_oat_file fptr_tests) + ] + + + + + + + +let complex_tests : suite = + [GradedTest ("complex hidden tests", 6, executed_oat_file + [] )] + + +let other_student_unit_tests : suite = + [ GradedTest ("Other Student Unit Tests", 1, []) ] + +let sp24_complex_tests = + List.map (fun (f, i, o) -> ("sp24_hw5_tests/" ^ f, i, o)) [] + +let other_students_complex_tests : suite = + [GradedTest ("Other Student Complex Tests", 4, + executed_oat_file sp24_complex_tests) ] + + +let manual_tests : suite = [ + GradedTest ("Posted Test Cases", 5, + [] + ) +] + +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 @ + complex_tests @ + functionality_tests @ + other_student_unit_tests @ + other_students_complex_tests @ + manual_tests diff --git a/hw5/test/studenttests.ml b/hw5/test/studenttests.ml new file mode 100644 index 0000000..86fe0fc --- /dev/null +++ b/hw5/test/studenttests.ml @@ -0,0 +1,18 @@ +open Testlib +open Util.Assert +open X86 +open Ll +module Driver = Oat.Driver +module Backend = Oat.Backend +module Typechecker = Oat.Typechecker +module Frontend = Oat.Frontend +module Tctxt = Oat.Tctxt +open Backend +open Driver + +(* Use this file to create additional test cases here to help you *) +(* debug your comiplper *) + +let student_local_tests : suite = [ + +] diff --git a/hw5/test/testlib.ml b/hw5/test/testlib.ml new file mode 100644 index 0000000..b1bb546 --- /dev/null +++ b/hw5/test/testlib.ml @@ -0,0 +1,157 @@ +open Util.Assert +open X86 +open Ll + +module Driver = Oat.Driver +module Backend = Oat.Backend +module Typechecker = Oat.Typechecker +module Frontend = Oat.Frontend +module Tctxt = Oat.Tctxt +open Backend +open Driver + +(* Do NOT modify this file -- we will overwrite it with our *) +(* own version when we test your project. *) + + +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::["bin/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_eqfs (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_eqfs (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 + diff --git a/hw5/util/assert.ml b/hw5/util/assert.ml deleted file mode 100644 index 6789b43..0000000 --- a/hw5/util/assert.ml +++ /dev/null @@ -1,160 +0,0 @@ -(* This code is mostly based on a course held at *) -(* University of Pennsylvania (CIS341) by Steve Zdancewic. *) - -(* Author: Steve Zdancewic *) -(* Modified by: Manuel Rigger *) -(* Modified by: Yann Girsberger *) - -(* Do NOT modify this file -- we will overwrite it *) -(* with our own version when testing your code. *) - - - -(* An assertion is just a unit->unit function that either *) -(* succeeds silently or throws an Failure exception. *) -type assertion = (unit -> unit) - -type 'a test = - | GradedTest of string * int * (string * 'a) list - | Test of string * (string * 'a) list - -type suite = (assertion test) list - - -(**************) -(* Assertions *) -exception Timeout - -let timeout_assert (time : int) (a : assertion) : assertion = - fun () -> - let handler = Sys.Signal_handle (fun _ -> raise Timeout) in - let old = Sys.signal Sys.sigalrm handler in - let reset_sigalrm () = Sys.set_signal Sys.sigalrm old in - ignore (Unix.alarm time); - try begin a (); reset_sigalrm () end - with Timeout -> reset_sigalrm (); failwith @@ Printf.sprintf "Timed out after %d seconds" time - | exc -> reset_sigalrm (); raise exc - -let timeout_test (time : int) (t : assertion test) : assertion test = - let map_timeout l = List.map (fun (i, a) -> (i, timeout_assert time a)) l in - match t with - | GradedTest (s, i, ls) -> GradedTest (s, i, map_timeout ls) - | Test (s, ls) -> Test (s, map_timeout ls) - -let timeout_suite (time : int) (s : suite) : suite = - List.map (timeout_test time) s - -let timeout_assert_const (a: assertion) : assertion = - timeout_assert 10 a - -let assert_eq v1 v2 : assertion = - timeout_assert_const (fun () -> if v1 <> v2 then failwith "not equal" else ()) - -let assert_eqf f v2 : assertion = - timeout_assert_const (fun () -> if (f ()) <> v2 then failwith "not equal" else ()) - -let assert_eqfs f v2 : assertion = - timeout_assert_const (fun () -> - let s1 = f () in - if s1 <> v2 then failwith @@ Printf.sprintf "not equal\n\texpected:%s\n\tgot:%s\n" v2 s1 - else ()) - - -let assert_fail : assertion = fun () -> failwith "assert fail" - - -(***************************) -(* Generating Test Results *) - -type result = - | Pass - | Fail of string - -type outcome = (result test) list - -let run_assertion (f:assertion) : result = - try - f (); - Pass - with - | Failure m -> Fail m - | e -> Fail ("test threw exception: " ^ (Printexc.to_string e)) - -let run_test (t:assertion test) : result test = - let run_case (cn, f) = (cn, run_assertion f) in - begin match t with - | GradedTest (n,s,cases) -> - Printf.eprintf "Running test %s\n%!" n; - GradedTest(n,s,List.map run_case cases) - - | Test (n, cases) -> - Printf.eprintf "Running test %s\n%!" n; - Test(n, List.map run_case cases) - end - -let run_suite (s:suite):outcome = - List.map run_test s - - - - - -(***********************) -(* Reporting functions *) - -let result_test_to_string (name_pts:string) (r:result test): string = - let string_of_case (name, res) = - begin match res with - | Pass -> "passed - " ^ name - | Fail msg -> "FAILED - " ^ name ^ ": " ^ msg - end - in - begin match r with - | GradedTest (_, _, cases) - | Test (_, cases) -> - name_pts ^ - (List.fold_left (fun rest -> fun case -> rest ^ "\n" ^ (string_of_case case)) "" cases) - end - -(* returns (name_pts, passed, failed, total, points_earned, max_given, max_hidden) *) -let get_results (t:result test) = - let num_passed cases = - List.fold_left (fun cnt (_,r) -> match r with Pass -> cnt + 1 | _ -> cnt) 0 cases in - let num_failed cases = - List.fold_left (fun cnt (_,r) -> match r with Fail _ -> cnt + 1 | _ -> cnt) 0 cases in - begin match t with - | GradedTest (name,pts,cases) -> - let passed = num_passed cases in - let failed = num_failed cases in - let total = List.length cases in - if total > 0 then - let points_earned = ((float_of_int passed) /. (float_of_int total)) *. (float_of_int pts) in - let name_pts = Printf.sprintf "%s (%1.f/%d points)" name points_earned pts in - (name_pts, passed, failed, total, points_earned, pts, 0) - else - let name_pts = Printf.sprintf "%s (?/%d points)" name pts in - (name_pts, passed, failed, total, 0.0, 0, pts) - | Test(name, cases) -> - let total = List.length cases in - let passed = num_passed cases in - let failed = num_failed cases in - (name, passed, failed, total, 0.0, 0, 0) - end - -let outcome_to_string (o:outcome):string = - let sep = "\n---------------------------------------------------\n" in - let helper (passed, failed, total, pts, maxg, maxh, str) (t:result test) = - let (name_pts, p, f, tot, s, mg, mh) = get_results t in - (passed + p, failed + f, total + tot, s +. pts, maxg + mg, maxh + mh, - str ^ "\n" ^ ( - if f > 0 then (result_test_to_string name_pts t) else - if tot > 0 then (name_pts ^ ":\n OK") else - (name_pts ^ ":\n Hidden") - ) - ) in - let (p,f,tot,pts,maxg, maxh,str) = List.fold_left helper (0,0,0,0.0,0,0,"") o in - str ^ sep ^ (Printf.sprintf "Passed: %d/%d\nFailed: %d/%d\nScore: %1.f/%d (given)\n ?/%d (hidden)" p tot f tot pts maxg maxh) - - - - diff --git a/hw5/util/platform.ml b/hw5/util/platform.ml deleted file mode 100644 index 807c27b..0000000 --- a/hw5/util/platform.ml +++ /dev/null @@ -1,156 +0,0 @@ -(* -------------------------------------------------------------------------- *) -(** Assembling and linking for X86. Depends on the underlying OS platform *) - - -open Printf -open Unix - -exception PlatformError of string * string - - -(* paths -------------------------------------------------------------------- *) -let path_sep = "/" -let dot_path = "./" -let output_path = ref "output" -let libs = ref [] -let lib_paths = ref [] -let lib_search_paths = ref [] -let include_paths = ref [] -let executable_name = ref "a.out" - -(* unix utility scripts ----------------------------------------------------- *) -let pp_cmd = ref "cpp -E " -let rm_cmd = ref "rm -rf " - - -(* -------------------------------------------------------------------------- *) -(* Platform specific configuration: Unix/Linux vs. Mac OS X *) - -let os = - let ic = Unix.open_process_in "uname -s" in - let uname = input_line ic in - let () = close_in ic in - uname (* One of "Darwin" or "Linux" *) - - -let linux = ref false -let mangle name = if !linux then name else ("_" ^ name) - -let osx_target_triple = "x86_64-apple-macosx10.13.0" -let linux_target_triple = "x86_64-unknown-linux" -let target_triple = ref osx_target_triple -let platform_flags = ref "" - - -(* Set the link commands properly, ensure output directory exists *) -let configure_os () = - if os = "Linux" then - begin - linux := true; - target_triple := linux_target_triple; - platform_flags := "" - end - else - if os = "Darwin" then - begin - linux := false; - target_triple := osx_target_triple; - platform_flags := "-fno-asynchronous-unwind-tables -mstackrealign" - end - else - failwith @@ "Unsupported OS detected: " ^ os - -(* verbose compiler output -------------------------------------------------- *) -let verbose = ref false -let verb msg = (if !verbose then (print_string msg; flush Stdlib.stdout)) - -let verb_os () = - verb @@ Printf.sprintf "* PLATFORM: %s TRIPLE: %s FLAGS %s\n" - os !target_triple !platform_flags - -let enable_verbose () = - verbose := true; - verb_os () - -(* create the output directory, which is assumed to exist *) -let create_output_dir () = - try ignore (stat !output_path) - with Unix_error (ENOENT,_,_) -> - (verb @@ Printf.sprintf "creating output directory: %s\n" !output_path); - mkdir !output_path 0o755 - - -(* clang invocation stuff --------------------------------------------------- *) -let common_flags = "-Wno-override-module" -let clang_ll_mode = "-S" -let as_mode = "-c" -let opt_level = ref "-O1 -Wall" -let clang args = - Printf.sprintf "clang %s -o " (String.concat " " args) - -let clang_cmd () = clang [clang_ll_mode; !opt_level; common_flags; !platform_flags] -let as_cmd () = clang [as_mode; !opt_level; common_flags; !platform_flags] -let link_cmd () = clang [common_flags; !opt_level; !platform_flags] - - -(* filename munging --------------------------------------------------------- *) -let path_to_basename_ext (path:string) : string * string = - (* The path is of the form ... "foo/bar/baz/.ext" *) - let paths = Str.split (Str.regexp_string path_sep) path in - let _ = if (List.length paths) = 0 then failwith @@ sprintf "bad path: %s" path in - let filename = List.hd (List.rev paths) in - match Str.split (Str.regexp_string ".") filename with - | [root] -> root, "" - | [root; ext] -> root, ext - | _ -> failwith @@ sprintf "bad filename: %s" filename - - -(* compilation and shell commands-------------------------------------------- *) - -(* Platform independent shell command *) -let sh (cmd:string) (ret:string -> int -> 'a) : 'a = - verb (sprintf "* %s\n" cmd); - match (system cmd) with - | WEXITED i -> ret cmd i - | WSIGNALED i -> raise (PlatformError (cmd, sprintf "Signaled with %d." i)) - | WSTOPPED i -> raise (PlatformError (cmd, sprintf "Stopped with %d." i)) - -(* Generate a file name that does not already exist. - basedir includes the path separator -*) -let gen_name (basedir:string) (basen:string) (baseext:string) : string = - let rec nocollide ofs = - let nfn = sprintf "%s/%s%s%s" basedir basen - (if ofs = 0 then "" else "_"^(string_of_int ofs)) baseext - in - try ignore (stat nfn); nocollide (ofs + 1) - with Unix_error (ENOENT,_,_) -> nfn - in nocollide 0 - - -let raise_error cmd i = - if i <> 0 then raise (PlatformError (cmd, sprintf "Exited with status %d." i)) - -let ignore_error _ _ = () - -let preprocess (dot_oat:string) (dot_i:string) : unit = - sh (sprintf "%s%s %s %s" !pp_cmd - (List.fold_left (fun s -> fun i -> s ^ " -I" ^ i) "" !include_paths) - dot_oat dot_i) raise_error - -let clang_compile (dot_ll:string) (dot_s:string) : unit = - sh (sprintf "%s%s %s" (clang_cmd ()) dot_s dot_ll) raise_error - -let assemble (dot_s:string) (dot_o:string) : unit = - sh (sprintf "%s%s %s" (as_cmd ()) dot_o dot_s) raise_error - -let link (mods:string list) (out_fn:string) : unit = - sh (sprintf "%s%s %s %s %s %s" (link_cmd ()) out_fn - (String.concat " " (mods @ !lib_paths)) - (List.fold_left (fun s -> fun i -> s ^ " -L" ^ i) "" !lib_search_paths) - (List.fold_left (fun s -> fun i -> s ^ " -I" ^ i) "" !include_paths) - (List.fold_left (fun s -> fun l -> s ^ " -l" ^ l) "" !libs)) - raise_error - - - diff --git a/hw5/util/range.ml b/hw5/util/range.ml deleted file mode 100644 index 03901c4..0000000 --- a/hw5/util/range.ml +++ /dev/null @@ -1,41 +0,0 @@ -open Lexing - -type pos = int * int (* Line number and column *) -type t = string * pos * pos - -let line_of_pos (l,_) = l -let col_of_pos (_,c) = c -let mk_pos line col = (line, col) - -let file_of_range (f,_,_) = f -let start_of_range (_,s,_) = s -let end_of_range (_,_,e) = e -let mk_range f s e = (f,s,e) -let valid_pos (l,c) = l >= 0 && c >=0 - -let merge_range ((f,s1,e1) as r1) ((f',s2,e2) as r2) = - if f <> f' then failwith @@ Printf.sprintf "merge_range called on different files: %s and %s" f f' - else - if not (valid_pos s1) then r2 else - if not (valid_pos s2) then r1 else - mk_range f (min s1 s2) (max e1 e2) - -let string_of_range (f,(sl,sc),(el,ec)) = - Printf.sprintf "%s:[%d.%d-%d.%d]" f sl sc el ec - -let ml_string_of_range (f,(sl,sc),(el,ec)) = - Printf.sprintf "(\"%s\", (%d, %d), (%d, %d))" f sl sc el ec - -let norange = ("__internal", (0,0), (0,0)) - -(* Creates a Range.pos from the Lexing.position data *) -let pos_of_lexpos (p:position) : pos = - mk_pos (p.pos_lnum) (p.pos_cnum - p.pos_bol) - -let mk_lex_range (p1:position) (p2:position) : t = - mk_range p1.pos_fname (pos_of_lexpos p1) (pos_of_lexpos p2) - -(* Expose the lexer state as a Range.t value *) -let lex_range lexbuf : t = - mk_lex_range (lexeme_start_p lexbuf) (lexeme_end_p lexbuf) - diff --git a/hw5/x86/testX86.ml b/hw5/x86/testX86.ml deleted file mode 100644 index 1b23983..0000000 --- a/hw5/x86/testX86.ml +++ /dev/null @@ -1,34 +0,0 @@ -open X86 -open Cunit - -let hello_label = mk_lbl_named "hellostr" -let puts_label = mk_lbl_named "_puts" (* gcc on linux/mac uses _ to munge names *) - -let main_seq = [ - Push (esp); - Mov (ebp, esp); - - Add (esp, Imm (-8l)); (* Not sure why this has to be 8 *) - Mov (stack_offset 0l, Lbl hello_label); - Call (Lbl puts_label); - - Mov (esp, ebp); - Pop (ebp); - Ret -] - -let main_bb = { - (mk_insn_block (mk_lbl_named "_main") main_seq) with - global = true -} - -let hello_data = { - link = false; - label = (mk_lbl_named "hellostr"); - value = GStringz "Hello, world!" -} - -let cu = [Data hello_data; Code main_bb] - -let _ = - print_endline (string_of_cunit cu)