let rec cast_to_c_stmt indent cast =
let indents = String.make indent '\t' in
let stmts = cast_to_c_stmtlist (indent+1) in
let cstmt = match cast with
| Decl((vtype, _) as vdecl, Some(expr), env) -> Format.sprintf "%s = ((struct %s*)(%s));" (vdecl_to_cstr vdecl) vtype (expr_to_cstr expr)
| Decl(vdecl, None, env) -> Format.sprintf "%s;" (vdecl_to_cstr vdecl)
| If(iflist, env) -> cast_to_c_if_chain indent iflist
| While(pred, [], env) -> Format.sprintf "while ( BOOL_OF( %s ) ) { }" (expr_to_cstr pred)
| While(pred, body, env) -> Format.sprintf "while ( BOOL_OF( %s ) ) {\n%s\n%s}" (expr_to_cstr pred) (stmts body) indents
| Expr(expr, env) -> Format.sprintf "( %s );" (expr_to_cstr expr)
| Return(Some(expr), env) -> Format.sprintf "return ( %s );" (expr_to_cstr expr)
| Return(_, env) -> "return;"
| Super(klass, fuid, []) -> Format.sprintf "%s((struct %s*)(this));" fuid (GenCast.get_tname klass)
| Super(klass, fuid, args) -> Format.sprintf "%s((struct %s*)(this), %s);" fuid (GenCast.get_tname klass) (String.concat ", " (List.map expr_to_cstr args)) in
indents ^ cstmt
and cast_to_c_stmtlist indent stmts =
String.concat "\n" (List.map (cast_to_c_stmt indent) stmts)
and cast_to_c_if_pred = function
| None -> ""
| Some(ifpred) -> Format.sprintf "if ( BOOL_OF( %s ) )" (expr_to_cstr ifpred)
and cast_to_c_if_chain indent pieces =
let indents = String.make indent '\t' in
let stmts = cast_to_c_stmtlist (indent + 1) in
let combine (pred, body) = Format.sprintf "%s {\n%s\n%s}" (cast_to_c_if_pred pred) (stmts body) indents in
String.concat " else " (List.map combine pieces)