The MIL Intermediate Code Representation

Your code generator will output "MIL" intermediate code, which can be directly executed by the mil_run MIL interpreter. The MIL interpreter assumes the following about a MIL program:

  1. Each line in the MIL file contains at most one MIL instruction
  2. Each line is at most 254 characters long
  3. All variables are defined before they are used
  4. Functions begin with a line of the form "func name" and end with the line "endfunc"

Please ensure that your generated MIL code meets the above four requirements.

As an example, for the primes.min MINI-L program, the corresponding MIL code might look like this. Note that your generated MIL code may look slightly different. However, your MIL code must behave the same way when it is executed by the mil_run MIL interpreter. As another example, the MIL code for the mytest.min MINI-L program might appear as it does here. As a final example, the MIL code for the the MIL code for the fibonacci.min MINI-L program might appear as it does here.

Each instruction in the MIL intermediate code representation is described in detail in the table below.

Functions in the MIL language

Functions in the MIL language start with a line of the form "func name" and end with the line "endfunc". Parameters are passed to mil functions with the param command, and values are returned from functions. Inside functions, arguments are referenced using a positional notation. For example, the first argument specified with the param instruction prior to the current function call would be accessible as the name $0. All arguments are passed by value, and recursive function calls are supported. A semantically valid MIL program must contain a function named main. All functions (with the exception of main) must return a scalar value. The main function must not return any value.

Syntax and Semantics

Syntax Semantics
Function Related Statements
param name adds the named parameter to the queue of parameters for the next function call
call name, dest calls the function with the specified name, storing the result in dest
ret src returns from the current function, passing src as the return value. src can be an immediate
Variable Declaration Statements
. name declares a name for a scalar variable
.[] name, n declares a name for an array variable consisting of n (must be a positive whole number) elements, with name[0] being the first element
Copy Statements
= dst, src dst = src (src can be an immediate)
Array Access Statements
=[] dst, src, index dst = src[index] (index can be an immediate)
[]= dst, index, src dst[index] = src (index and src can be immediates)
Input/Output Statements
.< dst read a value into dst from standard in
.[]< dst, index read a value into dst[index] from standard in
.> src write the value of src into standard out
.[]> src, index write the value of src[index] into standard out
Arithmetic Operator Statements (one or both source operands can be immediates)
+ dst, src1, src2 dst = src1 + src2
- dst, src1, src2 dst = src1 - src2
* dst, src1, src2 dst = src1 * src2
/ dst, src1, src2 dst = src1 / src2
% dst, src1, src2 dst = src1 % src2
Comparison Operator Statements (one or both source operands can be immediates)
< dst, src1, src2 dst = src1 < src2
<= dst, src1, src2 dst = src1 <= src2
!= dst, src1, src2 dst = src1 != src2
== dst, src1, src2 dst = src1 == src2
>= dst, src1, src2 dst = src1 >= src2
> dst, src1, src2 dst = src1 > src2
Logical Operator Statements (one or both source operands can be immediates)
|| dst, src1, src2 dst = src1 || src2 (logical OR)
&& dst, src1, src2 dst = src1 && src2 (logical AND)
! dst, src dst = !src (logical NOT)
Label Declaration Statements
: label declares a label
Branch Statements
:= label goto label
?:= label, predicate if predicate is true (1) goto label