C# (CSharp) kOS.Safe.Compilation Namespace

Nested Namespaces

kOS.Safe.Compilation.KS

Classes

Name Description
BinaryOpcode
BranchOpcode
CodePart
MLArgInfo
MLField
Opcode
OpcodeAddTrigger
OpcodeArgBottom Asserts that the next thing on the stack is the argument bottom marker. If it's not the argument bottom, it throws an error. This does NOT pop the value from the stack - it merely peeks at the stack top. The actual popping of the arg bottom value comes later when doing a return, or a program bottom exit.
OpcodeBogus Opcode to be returned when getting an opcode that doesn't exist (outside program range). This generally happens only when there's an exception that occurs outside running a program, and the KSPLogger has to have something valid returned or it throws an exception that hides the original exception it was trying to report.
OpcodeBranchIfFalse
OpcodeBranchIfTrue
OpcodeBranchJump
OpcodeCall
OpcodeCompareEqual
OpcodeCompareGT
OpcodeCompareGTE
OpcodeCompareLT
OpcodeCompareLTE
OpcodeCompareNE
OpcodeDup Push the thing atop the stack onto the stack again so there are now two of it atop the stack.
OpcodeEOF
OpcodeEOP
OpcodeEval Replaces the topmost thing on the stack with its evaluated, fully dereferenced version. For example, if the variable foo contains value 4, and the top of the stack is the identifier name "$foo", then this will replace the "$foo" with a 4.
OpcodeExists Tests if the identifier atop the stack is an identifier that exists in the system and is accessible in scope at the moment. If the identifier doesn't exist, or if it does but it's out of scope right now, then it results in a FALSE, else it results in a TRUE. The result is pushed onto the stack for reading. Note that the ident atop the stack must be formatted like a variable name (i.e. have the leading '$').
OpcodeGetIndex
OpcodeGetMember
OpcodeGetMethod OpcodeGetMethod is *exactly* the same thing as OpcodeGetMember, and is in fact a subclass of it. The only reason for the distinction is so that at runtime the Opcode can tell whether the getting of the member was done with method call syntax with parentheses, like SHIP:NAME(), or non-method call syntax, like SHIP:NAME. It needs to know whether there is an upcoming OpcodeCall coming next or not, so it knows whether the delegate will get dealt with later or if it needs to perform it now.
OpcodeLabelReset Most Opcode.Label fields are just string-ified numbers for their index position. But sometimes, when they are the entry point for a function call (from a lock expression), the label is an identifier string. When this is the case, then the mere position of the opcode within the program is not enough to store the label. Therefore, for import/export to an ML file, in this case the numeric label needs to be stored. It is done by creating a dummy opcode that is just a no-op instruction intended to be removed when the program is actually loaded into memory and run. It exists purely to store, as an argument, the label of the next opcode to follow it.
OpcodeLogicAnd
OpcodeLogicNot
OpcodeLogicOr
OpcodeLogicToBool
OpcodeMathAdd
OpcodeMathDivide
OpcodeMathMultiply
OpcodeMathNegate
OpcodeMathPower
OpcodeMathSubtract
OpcodeNOP
OpcodePop
OpcodePopScope Pops a variable namespace scope (for example, when a "}" is encountered in a block-scoping language like C++ or Java or C#.) From now on any local variables created within the previous scope are orphaned and gone forever ready to be garbage collected. It is possible to give it an argument to pop more than one nesting level of scope, to handle the case where you are breaking out of more than one nested level at once. (i.e. such as might happen with a break, return, or exit keyword).
OpcodePush
OpcodePushDelegate
OpcodePushDelegateRelocateLater This serves the same purpose as OpcodePushRelocateLater, except it's for use with UserDelegates instead of raw integer IP calls.
OpcodePushRelocateLater This class is an ugly placeholder to handle the fact that sometimes The compiler creates an OpcodePush that uses relocatable DestinationLabels as a temporary place to store their arguments in the list until they get added to the program. Basically, it's this: Old way: 1. In some cases, like setting up locks, Compiler would create an OpcodePush with Argument = null, and a DestinationLabel = something. 2. ProgramBuilder would rebuild the OpcodePush's Argument by copying it from the DestinationLabel as part of ReplaceLabels at runtime. The Problem: When storing this in the ML file, BOTH the Argument AND the DestinationLabel would need to be stored as [MLFields] even though they are never BOTH populated at the same time, which causes ridiculous bloat. New Way: 1. Compiler creates an OpcodePushRelocateLater with a DestinationLabel = something. 2. ProgramBuilder replaces this with a normal OpcodePush who's argument is set to the relocated value of the DestinationLabel. Why: This way the MLFile only stores 1 argument: If it's an OpcodePush, it stores OpcodePush.Argument. If it's an OpcodePushRelocateLater, then it stores just OpcodePushRelocateLater.DestinationLabel and no argument.
OpcodePushScope Pushes a new variable namespace scope (for example, when a "{" is encountered in a block-scoping language like C++ or Java or C#.) From now on any local variables created will be made in this new namespace.
OpcodeRemoveTrigger
OpcodeReturn Returns from an OpcodeCall, popping a number of scope depths off the stack as it does so. It evals the topmost thing on the stack. to remove any local variable references and replace them with their current values, and then performs the equivalent of a popscope, then jumps back to where the routine was called from. It also checks to ensure that the argument stack contains the arg bottom marker. If it does not, that proves the number of parameters consumed did not match the number of arguments passed and it throws an exception (to avoid stack misalignment that would happen if it tried to continue).
OpcodeSetIndex
OpcodeSetMember
OpcodeStore Consumes the topmost 2 values of the stack, storing the topmost stack value into a variable described by the next value down the stack.

If the variable does not exist in the local scope, then it will attempt to look for it in the next scoping level up, and the next one up, and so on until it hits global scope and if it still hasn't found it, it will CREATE the variable anew there, at global scope, and then store the value there.

This is the usual way to make a new GLOBAL variable, or to overwrite an existing LOCAL variable. Note that since this is the way to make a variable, it's impossible to make a variable that hasn't been given an initial value. Its the act of storing a value into the variable that causues it to exist. This is deliberate design.
OpcodeStoreExist Consumes the topmost 2 values of the stack, storing the topmost stack value into a variable described by the next value down the stack.

Unlike OpcodeStore, OpcodeStoreExist will NOT create the variable if it does not already exist. Instead it will cause an error. (It corresponds to kerboscript's @LAZYGLOBAL OFF directive).

OpcodeStoreGlobal Consumes the topmost 2 values of the stack, storing the topmost stack value into a variable described by the next value down the stack.

The variable will always be stored at a global scope, overwriting whatever else was there if the variable already existed.

It will ignore local scoping and never store the value in a local variable

It's impossible to make a variable that hasn't been given an initial value. Its the act of storing a value into the variable that causues it to exist. This is deliberate design.
OpcodeStoreLocal Consumes the topmost 2 values of the stack, storing the topmost stack value into a variable described by the next value down the stack.

The variable must not exist already in the local nesting level, and it will NOT attempt to look for it in the next scoping level up.

Instead it will attempt to create the variable anew at the current local nesting scope.

This is the usual way to make a new LOCAL variable. Do not attempt to use this opcode to store the value into an existing variable - just use it when making new variables. If you use it to store into an existing local variable, it will generate an error at runtime.

Note that since this is the way to make a variable, it's impossible to make a variable that hasn't been given an initial value. Its the act of storing a value into the variable that causues it to exist. This is deliberate design.
OpcodeSwap
OpcodeTestArgBottom Tests whether or not the next thing on the stack is the argument bottom marker. It pushes a true on top if it is, or false if it is not. In either case it does NOT consume the arg bottom marker, but just peeks for it.
OpcodeUnset
OpcodeWait
ProgramBuilder
ProgramBuilder.BuiltInPath
ProgramBuilder.ObjectFile
Script