@composita/compiler
Version:
Composita language compiler.
84 lines • 2.99 kB
JavaScript
import { BooleanDescriptor, CharacterDescriptor, FloatDescriptor, Instruction, IntegerDescriptor, JumpDescriptor, OperationCode, SystemCallDescriptor, TextDescriptor, } from '@composita/il';
var LabelTag;
(function (LabelTag) {
LabelTag[LabelTag["Tag"] = 0] = "Tag";
})(LabelTag || (LabelTag = {}));
export class Label {
constructor() {
this._labelTag = LabelTag.Tag;
}
}
export class ILAssembler {
constructor() {
this.targets = new Map();
this.origins = new Map();
this.code = new Array();
}
complete() {
this.fixLabels();
return this.code;
}
createLabel() {
return new Label();
}
setLabel(label) {
this.targets.set(label, this.code.length);
}
fixLabels() {
this.origins.forEach((origins, label) => {
const target = this.targets.get(label);
if (target === undefined) {
throw new Error('Cannot branch to unknown label.');
}
origins.forEach((origin) => {
const instruction = this.code[origin - 1];
if (instruction.code !== OperationCode.Branch &&
instruction.code !== OperationCode.BranchFalse &&
instruction.code !== OperationCode.BranchTrue) {
throw new Error('Not a jump instruction: ' + instruction.code + ', target: ' + target + ', origin: ' + origin);
}
this.code[origin - 1].arguments.push(new JumpDescriptor(target - origin));
});
});
}
emitLoadInteger(n) {
this.emit(OperationCode.LoadConstantInteger, new IntegerDescriptor(n));
}
emitLoadFloat(n) {
this.emit(OperationCode.LoadConstantFloat, new FloatDescriptor(n));
}
emitLoadCharacter(n) {
this.emit(OperationCode.LoadConstantCharacter, new CharacterDescriptor(n));
}
emitLoadText(n) {
this.emit(OperationCode.LoadConstantText, new TextDescriptor(n));
}
emitLoadBoolean(n) {
this.emit(OperationCode.LoadConstantBoolean, new BooleanDescriptor(n));
}
emitJump(opCode, label) {
this.emit(opCode);
if (!this.origins.has(label)) {
this.origins.set(label, new Array());
}
this.origins.get(label)?.push(this.code.length);
}
emitBranch(label) {
this.emitJump(OperationCode.Branch, label);
}
emitBranchFalse(label) {
this.emitJump(OperationCode.BranchFalse, label);
}
emitBranchTrue(label) {
this.emitJump(OperationCode.BranchTrue, label);
}
emitSystemCall(sysCall, numberOfArguments) {
const descriptor = new SystemCallDescriptor(sysCall);
descriptor.arguments.push(new IntegerDescriptor(numberOfArguments));
this.emit(OperationCode.SystemCall, descriptor);
}
emit(opCode, ...args) {
this.code.push(new Instruction(opCode, ...args));
}
}
//# sourceMappingURL=il-assembler.js.map