/** * Calls a function according to the given function number stating that the given number of * arguments have been pushed onto the stack * * <p>If callerIsBuiltIn then the caller is a builtIn function that called this function through * callFunctionFromBuiltIn. If address is -1 then a native function should be looked up and * called. */ public void callFunction( short address, short numberOfArguments, String functionName, boolean callerIsBuiltIn) throws ProgramException { stackFrames.addElement(new Integer(workingStackSegment.getStartAddress())); workingStackSegment.setStartAddress(getSP() + 5); if (callerIsBuiltIn) { pushValue(MAIN_STACK, VMProgram.BUILTIN_FUNCTION_ADDRESS); } else { pushValue(MAIN_STACK, program.getPC()); } pushFromRAM(MAIN_STACK, Definitions.LOCAL_POINTER_ADDRESS); pushFromRAM(MAIN_STACK, Definitions.ARG_POINTER_ADDRESS); pushFromRAM(MAIN_STACK, Definitions.THIS_POINTER_ADDRESS); pushFromRAM(MAIN_STACK, Definitions.THAT_POINTER_ADDRESS); ram.setValueAt( Definitions.ARG_POINTER_ADDRESS, (short) (getSP() - numberOfArguments - 5), false); ram.setValueAt(Definitions.LOCAL_POINTER_ADDRESS, getSP(), false); // enable in the arg segment only the number of args that were sent to the called function. argSegment.setEnabledRange( argSegment.getStartAddress(), argSegment.getStartAddress() + numberOfArguments - 1, true); if (address == VMProgram.BUILTIN_FUNCTION_ADDRESS) { // Perform some actions normally done in the function() method localSegment.setEnabledRange( localSegment.getStartAddress(), localSegment.getStartAddress() - 1, true); // no local variables callStack.pushFunction(functionName + " (built-in)"); staticSegment.setEnabledRange(0, -1, true); // empty static segment // Read parameters from the stack short[] params = new short[numberOfArguments]; for (int i = 0; i < numberOfArguments; ++i) { params[i] = argSegment.getValueAt(i); } // Call the built-in implementation builtInFunctionsRunner.callBuiltInFunction(functionName, params); } else if (address >= 0 || address < program.getSize()) { program.setPC(address); program.setPC(address); // make sure previouspc isn't pc-1 // which might happen if the calling // function called this function in the // last line before the "return" and // was declared just before this function. // In this case encountering the "function" // command will issue an error about // "missing return"... } else { error("Illegal call address"); } }
/** * Here Starts the code of a function according to the given function name that has the given * number of local variables. * * @param numberOfLocals The number of local variables */ public void function(short numberOfLocals) throws ProgramException { short newSP = (short) (getSP() + numberOfLocals); checkSP(newSP); workingStackSegment.setStartAddress(newSP); // disable non relevant range of the local segment - enable only the number // of locals of this function. localSegment.setEnabledRange(getSP(), newSP - 1, true); for (int i = 0; i < numberOfLocals; i++) { pushValue(MAIN_STACK, (short) 0); } String functionName = currentInstruction.getStringArg(); // adds the new function to the top of the call stack. callStack.pushFunction(functionName); // sets the static segment range setStaticRange(functionName); }