Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/vis15/src/compiler/typechecker/check-strand.sml
ViewVC logotype

View of /branches/vis15/src/compiler/typechecker/check-strand.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3410 - (download) (annotate)
Thu Nov 12 02:57:49 2015 UTC (3 years, 9 months ago) by jhr
File size: 4144 byte(s)
working on merge
(* check-strand.sml
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2015 The University of Chicago
 * All rights reserved.
 *)

structure CheckStrand : sig

    val check : Env.t * Env.context * ParseTree.strand_dcl -> AST.strand * Env.t

  end = struct

    structure PT = ParseTree
    structure TU = TypeUtil
    structure E = Env

    val err = TypeError.error

    datatype token = datatype TypeError.token

    fun checkMethod (env, cxt, meth) = (case meth
           of PT.M_Mark m => checkMethod (E.withEnvAndContext (env, cxt, m))
            | PT.M_Method(name, body) => let
                val body = CheckStmt.check (E.methodScope (env, name), cxt, body)
                in
                  AST.M_Method(name, body)
                end
          (* end case *))

    fun check (env, cxt, PT.SD_Mark m) = check (E.withEnvAndContext (env, cxt, m))
      | check (env0, cxt, PT.SD_Strand{name={span, tree=name}, params, state, methods}) = let
	  val env = E.strandScope env0
	  val (params, env) = CheckParams.check (env, cxt, Var.StrandParam, params)
	  val (sEnv, env') = E.insertStrand (env0, cxt, name, params)
        (* check the strand state-variable definitions *)
          val (vds, hasOutput, env) = let
		fun chkStateVar (env, cxt, PT.SVD_Mark m) =
		      chkStateVar (E.withEnvAndContext(env, cxt, m))
		  | chkStateVar (env, cxt, PT.SVD_VarDcl(isOut, vdcl)) = let
                      val kind = if isOut then AST.StrandOutputVar else AST.StrandStateVar
		      val (x, x', e') = CheckStmt.checkVarDecl (env, cxt, kind, vdcl)
		      in
                      (* check that strand variables have value types *)
                        if not(TU.isValueType(Var.monoTypeOf x'))
                          then err (cxt, [
                              S "strand variable ", V x', S " has non-value type ",
                              TY(Var.monoTypeOf x')
                            ])
                          else ();
		      (* add variable to strand environment *)
			StrandEnv.insertStateVar (sEnv, x, x');
		      (* check for redefinition *)
			E.checkForRedef (env, cxt, x);
		      (* return isOut, AST decl, and extended environment *)
			(isOut, (x', e'), E.insertLocal(env, cxt, x, x'))
		      end
		fun chkStateVar' (vd, (vds, hasOut, env)) = let
		      val (isOut, vd', env) = chkStateVar (env, cxt, vd)
		      in
			(vd'::vds, hasOut orelse isOut, env)
		      end
                val (vds, hasOutput, env) = List.foldl chkStateVar' ([], false, env) state
                in
                  (List.rev vds, hasOutput, env)
                end
        (* check the strand methods *)
          val methods = List.map (fn m => checkMethod (env, cxt, m)) methods
        (* get the list of methods defined by the user *)
          val methodNames = List.map (fn (AST.M_Method(name, _)) => name) methods
        (* if the stabilize method is not provided then add one, otherwise record the property *)
(* FIXME: perhaps we can get away without creating a dummy stabilize method! *)
          val methods = if List.exists (fn StrandUtil.Stabilize => true | _ => false) methodNames
                then (
                  Env.recordProp (env, StrandUtil.HasStabilizeMethod);
                  methods)
                else methods @ [AST.M_Method(StrandUtil.Stabilize, AST.S_Block[])]
	  in
(* FIXME: once there are global outputs, then it should be okay to have not strand outputs! *)
        (* check that there is at least one output variable *)
            if not hasOutput
              then err (cxt, [S "strand ", A name, S " does not have any outputs"])
              else ();
(* FIXME: should check for duplicate method definitions *)
            if not(List.exists (fn StrandUtil.Update => true | _ => false) methodNames)
              then err (cxt, [S "strand ", A name, S " is missing an update method"])
              else ();
	  (* we return the strand and the top-level environment with the strand added as a binding *)
            (AST.Strand{name = name, params = params, state = vds, methods = methods}, env')
	  end

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0