(**********************************************************************)
(* (c) Greg Morrisett, Neal Glew, Chris Hawblitzel,                   *)
(*     June 1998, all rights reserved.                                *)
(**********************************************************************)
type location = Poplocus.locus
type var = string
type type_name = string
type field_name = string
type scope = Static | Public | Extern | Abstract
type capability = ReadOnly | ReadWrite

type typ =
    VoidType
  | IntType
  | BooleanType
  | StringType
  | CharType
  | ArrayType of typ
  | FnType of typ * (typ list)
  | TupleType of (typ list)
  | NamedType of type_name

type const = 
    Int of int
  | Bool of bool
  | String of string
  | Char of char
  | Null of type_name

type primop = 
    Plus | Times | Minus | Div | Mod | Eq | Neq | Gt | Lt | Gte | Lte | Not |
    Bitnot | Bitand | Bitor | Bitxor | Bitlshift | Bitlrshift | Bitarshift |
    Size | Ord | Chr

type raw_exp =
    Const of const
  | ConstArray of exp list * typ option
  | Var of var
  | Primop of primop * (exp list)
  | Conditional of exp * exp * exp
  | Assign of exp * exp
  | AssignOp of exp * primop * exp  (* e.g., x+=1, x[i] *= 3 *)
  | FunCall of exp * (exp list)
  | NewStruct of type_name * (exp list)
  | StructMember of exp * field_name
  | NewUnion of type_name * field_name * (exp option)
  | NewTuple of (exp list)
  | TupleMember of exp * int
  | Subscript of exp * exp
  | NewArray of exp * exp
  | Compile of fndecl
  | Hole of exp
and exp = 
    { mutable exp_typ: typ option;
      raw_exp: raw_exp;
      exp_loc: location
    } 

and raw_stmt =
    Skip
  | Exp of exp
  | Seq of stmt * stmt
  | Return of exp option
  | IfThenElse of exp * stmt * stmt
  | While of exp * stmt
  | Break 
  | Continue
  | For of exp * exp * exp * stmt
  | IntSwitch of exp * (int * stmt) list * stmt
  | CharSwitch of exp * (char * stmt) list * stmt
  | UnionSwitch of 
      exp * (field_name * (var option) * stmt) list * (stmt option)
  | Decl of var * typ * (exp option) ref * stmt
  | Suspend of stmt
  | Resume of stmt
  | Do of stmt * exp
and stmt = raw_stmt * location
and fndecl = { fn_static: bool;
		fn_name: var;
		fn_ret_type: typ;
		fn_args: (var * typ) list;
		fn_body: stmt
	      } 

type struct_field = (field_name * capability * typ)
type union_field = (field_name * typ)


type structdecl = { st_scope: scope;
		    st_name: type_name;
		    st_possibly_null: bool;
		    st_fields: struct_field list
		  }	
type uniondecl = { un_scope: scope;
		   un_name: type_name;
		   un_possibly_null: bool;
		   un_fields: union_field list
		 }	

type raw_top_decl =
    FunDecl of fndecl
  | StructDecl of structdecl
  | UnionDecl of uniondecl
  | ExternFun of typ * var * (typ list)
  | ExternType of type_name * bool (* bool indicates option *)
  | ExternVal of (var * typ)
  | GlobalDecl of (scope * var * typ * (exp option) ref)
and top_decl = raw_top_decl * location

(* should fix function and array types to be inline with the parsed syntax *)
let rec typ2string t = 
  match t with
    VoidType -> "void"
  | IntType -> "int"
  | BooleanType -> "boolean"
  | StringType -> "string"
  | CharType -> "char"
  | ArrayType t -> ("array["^(typ2string t)^"]")
  | FnType (t,ts) -> ("("^types2string ts^")->"^typ2string t)
  | TupleType ts -> "*("^(types2string ts)^")"
  | NamedType n -> n
and types2string ts = 
  match ts with
    [] -> ""
  | [t] -> typ2string t
  | t::ts -> ((typ2string t)^","^(types2string ts))

let eqtype t1 t2 = (t1 = t2)
