WIP type-checking -- check record expressions
[tiger.ml.git] / compiler / src / lib / tiger / tiger_semant.ml
index 659bb85..ca4b489 100644 (file)
@@ -56,6 +56,8 @@ end = struct
   let check_int expty ~pos : unit =
     check_same {exp=(); ty=Type.Int} expty ~pos
 
+  (* TODO: actual_ty *)
+
   let rec transExp ~env exp =
     let rec trexp exp =
       (match exp with
@@ -65,12 +67,37 @@ end = struct
           return_int
       | A.StringExp {string=_; _} ->
           return_string
-      | A.CallExp {func=_; args=_; pos=_} ->
-          unimplemented ()
+      | A.CallExp {func; args; pos} ->
+          (match env_get_val ~sym:func ~env ~pos with
+          | Value.Fun {formals; result} ->
+              List.iter2 formals args ~f:(fun ty_expected exp_given ->
+                check_same {exp=(); ty = ty_expected} (trexp exp_given) ~pos;
+              );
+              return result
+          | Value.Var _ ->
+              E.raise (E.Id_not_a_function {id=func; pos})
+          )
       | A.OpExp {oper; left; right; pos} ->
           trop oper ~left ~right ~pos
-      | A.RecordExp {fields=_; typ=_; pos=_} ->
-          unimplemented ()
+      | A.RecordExp {fields=field_exps; typ; pos} ->
+          let ty = env_get_typ ~sym:typ ~env ~pos in
+          Type.if_record
+            ty
+            ~f:(fun field_tys ->
+              List.iter field_exps ~f:(fun (field, exp, pos) ->
+                (match List.assoc_opt field field_tys with
+                | Some field_ty ->
+                    check_same {exp=(); ty=field_ty} (trexp exp) ~pos
+                | None ->
+                    E.raise
+                      (E.No_such_field_in_record {field; record=ty; pos})
+                )
+              )
+            )
+            ~otherwise:(fun () ->
+              E.raise (E.Wrong_type_used_as_record {ty_id=typ; ty; pos})
+            );
+          return ty
       | A.SeqExp exps ->
           (* Ignoring value because we only care if a type-checking exception
            * is raised in one of trexp calls: *)
@@ -134,8 +161,13 @@ end = struct
               )
             )
             ~otherwise:(fun () -> E.raise (E.Exp_not_a_record {ty; pos}))
-      | A.SubscriptVar {var=_; exp=_; pos=_} ->
-          unimplemented ()
+      | A.SubscriptVar {var; exp; pos} ->
+          let {exp=_; ty} = trvar var in
+          check_int (trexp exp) ~pos;
+          Type.if_array
+            ty
+            ~f:(fun ty_elements -> return ty_elements)
+            ~otherwise:(fun () -> E.raise (E.Exp_not_an_array {ty; pos}))
       )
     and trop oper ~left ~right ~pos =
       let expty_left  = trexp left in
This page took 0.022218 seconds and 4 git commands to generate.