Some small fixes and guide about stack frames.
EMC in general:
- "Push Record" actually pushes current line and frame
pointer. It doesn't save stack pointer as I mentioned.
Nevertheless it's still used to call subroutine
with "Goto".
- "Pop Record" retrieves frame pointer and old position
(obvious) It's still used to return from subroutine.
- The script will stop only if there's "Pop Record"
or "Return" called when the stack is empty (generally
from main function) or if there's unsupported
command/argument so you can't hang the game cause of
bad command.
- You could still hang the game if the stack is overflowed
(it will affect private data)
- Variables. This is important: The 5 variables which I
mentioned are no longer local. They have very specific
purpose because they are used also by external
functions. So they mustn't be used as your temporary
variables. Use stack frame instead. Because of this fact
I briefly called them "global registers", and the
functions: "Push/Pop Reg".
HOW TO USE FUNCTION ARGUMENTS AND LOCAL VARIABLES:
- Read this if you're not familiar how to program them low-
level or just want to know how to implement them in this
script.
- In order to use local variables you must create stack
frame: simply call "Add SP n" where n is desired size
(number of variables).
Do this always as your first command in the function
so your variables will be easily accessed later!
To remove the stack frame use "Add SP n" with the same
size.
- "Push/Pop Frame (-)".
Use this functions to read/write your variables.
- Putting functions for arguments.
Use any of "Push" commands to put arguments for a
function then call the function with "Push Record"
and "Goto" (or simply "Exec" if it's external).
Remember to retrieve stack space with "Add SP n" where n
is the number of arguments you pushed!
- "Push/Pop Frame (+)"
These are used to access function arguments inside the
function, which can be considered as your extra variables.
- Important: In both cases use as lowest command argument
1. Never 0, because it will override with latest "Push
Record" values. The highest is the stack frame size or
number of function arguments.
Simple example:
Let's say we have subroutine "calcmean( x, y )" which
calcs arithmetic mean of two numbers. (It can also be
done without using local variables)
main:
...
Push 5 ; y (push in reverse order)
Push 9 ; x
Push Record ; save position
Goto calcmean ; goto label 'calcmean'
Add SP 2 ; remove function args from stack
...
Pop Record ; stop script
calcmean:
Sub SP 1 ; make space for one variable
PushFrame(+) 1 ; this will access "x" argument
PushFrame(+) 2 ; this will access "y" argument
Eval "+" ; this will add both numbers
PopFrame(-) 1 ; store sum in our variable
Push 2 ; push 2
PushFrame(-) 1 ; push our sum
Eval "/" ; divide numbers
PopRetCode ; store result as return code
Add SP 1 ; remove stack frame
Pop Record ; return from subroutine
- I hope it's clear but don't hesitate to reply.
BUILD.EMC
- What I call attachment is simply forcing unit to move to
current structure (or any other location: cell or unit).
- The "global register #4" (previous variable) can store
only ID of unit we wish to attach because external
functions will refer to it that way.
That is why I changed its status to global.