Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some improvements on primitives #48

Merged
merged 8 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion src/memory/memory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { InconsistentMemory, SegmentOutOfBounds } from 'errors/memory';
import { MaybeRelocatable, Relocatable } from 'primitives/relocatable';
import { Relocatable } from 'primitives/relocatable';
import { MaybeRelocatable } from 'primitives/maybeRelocatable';

export class Memory {
data: Array<Array<MaybeRelocatable>>;
Expand Down
23 changes: 7 additions & 16 deletions src/primitives/felt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MaybeRelocatable, Relocatable } from './relocatable';

import { Relocatable } from './relocatable';
import { MaybeRelocatable, isFelt, isRelocatable } from './maybeRelocatable';
import { ForbiddenOperation, OutOfRangeBigInt } from 'errors/primitives';

export class Felt {
Expand All @@ -15,43 +15,38 @@ export class Felt {
}

add(other: MaybeRelocatable): Felt {
if (!(other instanceof Felt)) {
if (!isFelt(other)) {
throw new ForbiddenOperation();
}

return new Felt(this.inner + other.inner);
}

sub(other: MaybeRelocatable): Felt {
if (!(other instanceof Felt)) {
if (!isFelt(other)) {
throw new ForbiddenOperation();
}

return new Felt(this.inner - other.inner);
}

mul(other: MaybeRelocatable): Felt {
if (!(other instanceof Felt)) {
if (!isFelt(other)) {
throw new ForbiddenOperation();
}

return new Felt(this.inner * other.inner);
}

div(other: MaybeRelocatable): Felt {
if (!(other instanceof Felt) || other.inner === 0n) {
if (!isFelt(other) || other.inner === 0n) {
throw new ForbiddenOperation();
}

return new Felt(this.inner / other.inner);
}

eq(other: MaybeRelocatable): boolean {
if (other instanceof Relocatable) {
return false;
}

return this.inner == other.inner;
return !isRelocatable(other) && this.inner === other.inner;
}

toString(): string {
Expand All @@ -65,8 +60,4 @@ export class Felt {
toHexString(): string {
return this.inner.toString(16);
}

static isFelt(maybeRelocatable: MaybeRelocatable): maybeRelocatable is Felt {
return maybeRelocatable instanceof Felt;
}
}
28 changes: 28 additions & 0 deletions src/primitives/maybeRelocatable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Felt } from './felt';
import { Relocatable } from './relocatable';

export type MaybeRelocatable = Relocatable | Felt;

export function isFelt(
maybeRelocatable: MaybeRelocatable
): maybeRelocatable is Felt;
export function isFelt(
maybeRelocatable: MaybeRelocatable | number
): maybeRelocatable is Felt;
export function isFelt(
maybeRelocatable: MaybeRelocatable | number
): maybeRelocatable is Felt {
return maybeRelocatable instanceof Felt;
}

export function isRelocatable(
maybeRelocatable: MaybeRelocatable
): maybeRelocatable is Relocatable;
export function isRelocatable(
maybeRelocatable: Relocatable | number
): maybeRelocatable is Relocatable;
export function isRelocatable(
maybeRelocatable: MaybeRelocatable | number
): maybeRelocatable is Relocatable {
return maybeRelocatable instanceof Relocatable;
}
29 changes: 10 additions & 19 deletions src/primitives/relocatable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import {
OffsetUnderflow,
SegmentError,
} from 'errors/primitives';

export type MaybeRelocatable = Relocatable | Felt;
import { MaybeRelocatable, isFelt, isRelocatable } from './maybeRelocatable';

export class Relocatable {
segment: number;
Expand All @@ -21,14 +20,14 @@ export class Relocatable {
add(other: Relocatable): never;
add(other: MaybeRelocatable): MaybeRelocatable;
add(other: MaybeRelocatable | number): MaybeRelocatable {
if (other instanceof Felt) {
if (isFelt(other)) {
const offset = new Felt(BigInt(this.offset));
const newOffset = Number(offset.add(other));

return new Relocatable(this.segment, newOffset);
}

if (other instanceof Relocatable) {
if (isRelocatable(other)) {
throw new ForbiddenOperation();
}

Expand All @@ -40,7 +39,7 @@ export class Relocatable {
sub(other: Relocatable): Felt;
sub(other: MaybeRelocatable): MaybeRelocatable;
sub(other: MaybeRelocatable | number): MaybeRelocatable {
if (other instanceof Felt) {
if (isFelt(other)) {
const delta = Number(other);

if (this.offset < delta) {
Expand All @@ -49,7 +48,7 @@ export class Relocatable {
return new Relocatable(this.segment, this.offset - delta);
}

if (other instanceof Relocatable) {
if (isRelocatable(other)) {
if (this.offset < other.offset) {
throw new OffsetUnderflow();
}
Expand All @@ -69,24 +68,16 @@ export class Relocatable {
}

eq(other: MaybeRelocatable): boolean {
if (other instanceof Felt) {
return false;
}
if (other.offset === this.offset && other.segment === this.segment) {
return true;
}
return false;
return (
!isFelt(other) &&
other.offset === this.offset &&
other.segment === this.segment
);
}

toString(): string {
return `${this.segment}:${this.offset}`;
}

static isRelocatable(
maybeRelocatable: MaybeRelocatable
): maybeRelocatable is Relocatable {
return maybeRelocatable instanceof Relocatable;
}
}

/**
Expand Down
31 changes: 18 additions & 13 deletions src/vm/virtualMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from 'errors/virtualMachine';
import { Felt } from 'primitives/felt';
import { Instruction } from './instruction';
import { MaybeRelocatable, Relocatable } from 'primitives/relocatable';
import { Relocatable } from 'primitives/relocatable';
import { InstructionError } from 'errors/memory';

import {
Expand All @@ -22,6 +22,11 @@ import { Memory } from 'memory/memory';
import { ProgramCounter, MemoryPointer } from 'primitives/relocatable';

import { Op1Source } from 'vm/instruction';
import {
MaybeRelocatable,
isFelt,
isRelocatable,
} from 'primitives/maybeRelocatable';

// operand 0 is the first operand in the right side of the computation
// operand 1 is the second operand in the right side of the computation
Expand Down Expand Up @@ -94,7 +99,7 @@ export class VirtualMachine {
throw new Op0Undefined();
}

if (!Relocatable.isRelocatable(op0)) {
if (!isRelocatable(op0)) {
throw new Op0NotRelocatable();
}
baseAddr = op0;
Expand All @@ -110,7 +115,7 @@ export class VirtualMachine {
throw new EndOfInstructionsError();
}

if (!(maybeEncodedInstruction instanceof Felt)) {
if (!isFelt(maybeEncodedInstruction)) {
throw new InstructionError();
}

Expand Down Expand Up @@ -245,7 +250,7 @@ export class VirtualMachine {
case 'op0 * op1':
if (dst !== undefined && op1 !== undefined) {
try {
if (!Felt.isFelt(dst)) {
if (!isFelt(dst)) {
throw new Error();
}
// op0 = res / op1
Expand Down Expand Up @@ -286,7 +291,7 @@ export class VirtualMachine {
// op1 = dst / op0
if (dst !== undefined && op0 !== undefined) {
try {
if (!Felt.isFelt(dst)) {
if (!isFelt(dst)) {
throw new Error();
}
return dst.div(op0);
Expand All @@ -312,7 +317,7 @@ export class VirtualMachine {
case 'op0 + op1':
return op0.add(op1);
case 'op0 * op1':
if (!Felt.isFelt(op0)) {
if (!isFelt(op0)) {
throw new ExpectedFelt();
}
return op0.mul(op1);
Expand Down Expand Up @@ -362,7 +367,7 @@ export class VirtualMachine {
if (operands.res === undefined) {
throw new UnconstrainedResError();
}
if (!Relocatable.isRelocatable(operands.res)) {
if (!isRelocatable(operands.res)) {
throw new ExpectedRelocatable();
}
this.pc = operands.res;
Expand All @@ -374,7 +379,7 @@ export class VirtualMachine {
throw new UnconstrainedResError();
}

if (!Felt.isFelt(operands.res)) {
if (!isFelt(operands.res)) {
throw new ExpectedFelt();
}
this.pc = this.pc.add(operands.res);
Expand All @@ -386,13 +391,13 @@ export class VirtualMachine {
if (operands.dst === undefined) {
throw new InvalidDstOperand();
}
if (Felt.isFelt(operands.dst) && operands.dst.eq(Felt.ZERO)) {
if (isFelt(operands.dst) && operands.dst.eq(Felt.ZERO)) {
this.incrementPc(instruction.size());
} else {
if (operands.op1 === undefined) {
throw new InvalidOp1();
}
if (!Felt.isFelt(operands.op1)) {
if (!isFelt(operands.op1)) {
throw new ExpectedFelt();
}
this.pc = this.pc.add(operands.op1);
Expand All @@ -415,10 +420,10 @@ export class VirtualMachine {
if (operands.dst === undefined) {
throw new InvalidDstOperand();
}
if (Felt.isFelt(operands.dst)) {
if (isFelt(operands.dst)) {
this.fp = this.fp.add(operands.dst);
}
if (Relocatable.isRelocatable(operands.dst)) {
if (isRelocatable(operands.dst)) {
this.fp = operands.dst;
}
break;
Expand All @@ -433,7 +438,7 @@ export class VirtualMachine {
if (operands.res === undefined) {
throw new UnconstrainedResError();
}
if (!Felt.isFelt(operands.res)) {
if (!isFelt(operands.res)) {
throw new ExpectedFelt();
}

Expand Down
Loading