let rec compile_global_expression expr = match expr with
Ast.SynFunctionDeclare (dt, name, arglist) -> [NoteFunction name]
| Ast.SynRemotableFunctionDeclare (dt, name, arglist) -> []
| Ast.SynFunctionDefine ((dt, name, arglist), expr_list) ->
compile_function_definition name arglist expr_list
| Ast.SynTemplatedDeclare (_,expr) -> compile_global_expression expr
| Ast.SynTemplatedDefine (_,expr) -> compile_global_expression expr
| Ast.SynStructDeclare sdecl -> []
| Ast.SynGlobalEnumDeclare edecl -> []
| Ast.SynGlobalVarDeclare vdecl ->
(match vdecl with
Ast.SynVarDeclareNoInit (dt,v) ->
let dt_result = compile_datatype_init dt in
let _ = init_buffer := !init_buffer @ dt_result @ [SetVar v] in
[DeclareGlobal v]
| _ -> raise_compile_error ["Unexpected compile error: cannot initialize a variable in the global scope."])
| Ast.SynStateMachine _ ->
raise_compile_error ["Unexpected compile error: source-to-source compilation of state machine failed."]
| Ast.SynInclude data ->
match !data with
Ast.IncludeAst ast -> compile_global_expression_list ast
| Ast.IncludeFileName s ->
raise_compile_error ["Unexpected compile error: include ";s;" was not typechecked properly."]
and compile_global_expression_list src_prog =
match src_prog with
cur::rest ->
let curbuf = compile_global_expression cur in
let restbuf = compile_global_expression_list rest in
curbuf@restbuf
| [] -> []
and compile_ir src_prog =
try
let _ = init_buffer := [] in
let init_label = make_label "INIT" in
let program_result = compile_global_expression_list src_prog in
[Instruction (Annotation (concat ["init ";init_label]))]
@ program_result
@ [Instruction (Annotation (concat ["function ";init_label;" 0"]));
Instruction (Label (init_label))]
@ !init_buffer
@ [Instruction Return]
with
Ircompile_error s ->
let _ = output_string stderr s in
let _ = output_string stderr "\n" in
let _ = flush stderr in
raise (Ircompile_error s)