Instructions

Brez spremembe interpreterja spremenite svoj prevajalnik tako, da se pri klicu podprograma najprej izračuna skrajno levi argument, potem pa ostali argumenti od desne proti levi.

Test

fun putint(c: int): void  
fun putchar(c: char): void  
fun puts(s: ^char): void  
  
fun f(c: int): int =  
    putint(c),  
    putchar('\0x0A'),  
    return c  
  
fun g(c1: int, c2: int, c3: int, c4: int): void =  
    putchar('\0x0A'),  
    puts("Parameters:"), putchar('\0x0A'),  
    putint(c1),  
    putchar('\0x0A'),  
    putint(c2),  
    putchar('\0x0A'),  
    putint(c3),  
    putchar('\0x0A'),  
    putint(c4)  
  
fun main(): int =  
    puts("Argument evaluation:"), putchar('\0x0A'),  
    g(f(1), f(4), f(3), f(2)),  
    return 0

Out

Before

Argument evaluation:
1
4
3
2

Parameters:
1
4
3
2

After

Argument evaluation:
1
2
3
4

Parameters:
1
4
3
2

Code

/imcgen/IMC.java

public class IMC {
    // ... other code ...
    public static class CALL extends Expr {
        public final Expr addr;
        public final Vector<Long> offs;
        public final Vector<Expr> args;
// --- ADDED: Store AST argument expressions ---
        public final AST.Nodes<AST.Expr> argExprs;
 
        /**
         * Constructs a function call.
         *
         * @param addr     The address of the function.
         * @param offs     The offsets of arguments.
         * @param args     The values of arguments.
         * @param argExprs The AST expressions of arguments
         */
        public CALL(Expr addr, Vector<Long> offs, Vector<Expr> args, AST.Nodes<AST.Expr> argExprs) {
            this.addr = addr;
            this.offs = new Vector<>(offs);
            this.args = new Vector<>(args);
            this.argExprs = argExprs;
        }
        // ... other code ...
    }
}

/imcgen/ImcGenerator.java

public class ImcGenerator implements AST.FullVisitor<IMC.Instr, ImcGenerator.Info> {
    // ... other code ...
    @Override
    public IMC.Instr visit(AST.CallExpr callExpr, Info info) {
        // ... other code ...
// --- MODIFIED: added new parameter
        IMC.Expr imcExpr = new IMC.CALL(funExprAddrImc, argOffsets, argImcs, callExpr.argExprs);
        ImcGen.expr.put(callExpr, imcExpr);
        return imcExpr;
    }
    // ... other code ...
}

/imclin/LinearizeImc.java

public class LinearizeImc implements IMC.FullVisitor<IMC.Expr, LinearizeImc.Info> {
    // ... other code ...
 
    @Override
    public IMC.Expr visit(IMC.CALL call, Info info) {
        info.allowCall = false;
 
        // ... other code ...
        
// --- CHANGED ---
        // Arguments: first all ints from left to right  
		for (int i = 0; i < argsCount; i++) {  
		    if (SemAn.ofType.get(call.argExprs.get(i)) instanceof TYP.IntType) {  
		        evaluatedArgs[i] = call.args.get(i + 1).accept(this, info);  
		    }  
		}  
		// then all others from right to left  
		for (int i = argsCount-1; i >= 0; i--) {  
		    if (!(SemAn.ofType.get(call.argExprs.get(i)) instanceof TYP.IntType)) {  
		        evaluatedArgs[i] = call.args.get(i+1).accept(this, info);  
		    }  
		}
		
		// ... other code ...
		
		info.allowCall = previousAllowCall;
// --- MODIFIED: added new parameter
        IMC.CALL callImc = new IMC.CALL(linearizedAddr, call.offs, linearizedArgs, call.argExprs);
        if (info.allowCall) {
            return callImc;
        } else {
            // ... existing code ...
        }
    }
 
    // ... other code ...
}