phantasmal-world/src/scripting/instructions.ts

86 lines
1.9 KiB
TypeScript
Raw Normal View History

import { TYPE_I_LABEL_VAR, TYPE_REG_REF_VAR, Opcode } from "./opcodes";
/**
* Instruction invocation.
*/
export class Instruction {
/**
* Byte size of the argument list.
*/
readonly arg_size: number = 0;
/**
* Byte size of the entire instruction, i.e. the sum of the opcode size and all argument sizes.
*/
readonly size: number;
/**
* Maps each parameter by index to its arguments.
*/
readonly param_to_args: Arg[][] = [];
constructor(readonly opcode: Opcode, readonly args: Arg[]) {
const len = Math.min(opcode.params.length, args.length);
for (let i = 0; i < len; i++) {
const type = opcode.params[i].type;
const arg = args[i];
this.param_to_args[i] = [];
switch (type) {
case TYPE_I_LABEL_VAR:
case TYPE_REG_REF_VAR:
this.arg_size++;
for (let j = i; j < args.length; j++) {
this.param_to_args[i].push(args[j]);
this.arg_size += args[j].size;
}
break;
default:
this.arg_size += arg.size;
this.param_to_args[i].push(arg);
break;
}
}
this.size = opcode.size + this.arg_size;
}
}
/**
* Instruction argument.
*/
export type Arg = {
value: any;
size: number;
};
export enum SegmentType {
Instructions,
Data,
String,
}
/**
* Segment of object code.
*/
export type Segment = InstructionSegment | DataSegment | StringSegment;
export type InstructionSegment = {
type: SegmentType.Instructions;
labels: number[];
instructions: Instruction[];
};
export type DataSegment = {
type: SegmentType.Data;
labels: number[];
data: ArrayBuffer;
};
export type StringSegment = {
type: SegmentType.String;
labels: number[];
value: string;
};