Implement basic integer math operations

This commit is contained in:
2026-08-01 13:50:24 -05:00
parent e728c3fdfa
commit 6e0eb2786e
8 changed files with 521 additions and 166 deletions

24
src/vm/commands/abs.ts Normal file
View File

@@ -0,0 +1,24 @@
import {Command} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
import {Awaitable} from "../../util/types.js";
export class Abs extends Command<{}> {
attemptParse(): Awaitable<{}> {
return {}
}
getDisplayName(): string {
return 'abs'
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'abs')
}
async execute(vm: StrVM): Promise<StrVM> {
return vm.replaceContextMatchingTerm({
int: sub => Math.abs(sub),
})
}
}

29
src/vm/commands/divide.ts Normal file
View File

@@ -0,0 +1,29 @@
import {Command, ParseContext, StrTerm} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
export type DivideData = {
val: StrTerm,
}
export class Divide extends Command<DivideData> {
async attemptParse(context: ParseContext): Promise<DivideData> {
return {
val: await context.popTerm(),
}
}
getDisplayName(): string {
return 'divide'
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'divide')
}
async execute(vm: StrVM, data: DivideData): Promise<StrVM> {
return vm.replaceContextMatchingTerm(ctx => ({
int: sub => sub / ctx.resolveInt(data.val),
}))
}
}

View File

@@ -60,9 +60,15 @@ import {Convert} from "./convert.js";
import {While} from "./while.js";
import {Table} from "./table.js";
import {Push} from "./push.js";
import {Plus} from "./plus.js";
import {Minus} from "./minus.js";
import {Times} from "./times.js";
import {Divide} from "./divide.js";
import {Abs} from "./abs.js";
export type Commands = Command<CommandData>[]
export const commands: Commands = [
new Abs,
new Assign,
new Call,
new Chunk,
@@ -71,6 +77,7 @@ export const commands: Commands = [
new Contains,
new Convert,
new Copy,
new Divide,
new Drop,
new Each,
new Edit,
@@ -91,11 +98,13 @@ export const commands: Commands = [
new Load,
new Lower,
new LSub,
new Minus,
new Missing,
new On,
new OutFile,
new Over,
new Paste,
new Plus,
new Prefix,
new Push,
new Quote,
@@ -113,6 +122,7 @@ export const commands: Commands = [
new Suffix,
new Table,
new Take,
new Times,
new To,
new Trim,
new Undo,

29
src/vm/commands/minus.ts Normal file
View File

@@ -0,0 +1,29 @@
import {Command, ParseContext, StrTerm} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
export type MinusData = {
val: StrTerm,
}
export class Minus extends Command<MinusData> {
async attemptParse(context: ParseContext): Promise<MinusData> {
return {
val: await context.popTerm(),
}
}
getDisplayName(): string {
return 'minus'
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'minus')
}
async execute(vm: StrVM, data: MinusData): Promise<StrVM> {
return vm.replaceContextMatchingTerm(ctx => ({
int: sub => sub - ctx.resolveInt(data.val),
}))
}
}

29
src/vm/commands/plus.ts Normal file
View File

@@ -0,0 +1,29 @@
import {Command, ParseContext, StrTerm} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
export type PlusData = {
val: StrTerm,
}
export class Plus extends Command<PlusData> {
async attemptParse(context: ParseContext): Promise<PlusData> {
return {
val: await context.popTerm(),
}
}
getDisplayName(): string {
return 'plus'
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'plus')
}
async execute(vm: StrVM, data: PlusData): Promise<StrVM> {
return vm.replaceContextMatchingTerm(ctx => ({
int: sub => sub + ctx.resolveInt(data.val),
}))
}
}

29
src/vm/commands/times.ts Normal file
View File

@@ -0,0 +1,29 @@
import {Command, ParseContext, StrTerm} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
export type TimesData = {
val: StrTerm,
}
export class Times extends Command<TimesData> {
async attemptParse(context: ParseContext): Promise<TimesData> {
return {
val: await context.popTerm(),
}
}
getDisplayName(): string {
return 'times'
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'times')
}
async execute(vm: StrVM, data: TimesData): Promise<StrVM> {
return vm.replaceContextMatchingTerm(ctx => ({
int: sub => sub * ctx.resolveInt(data.val),
}))
}
}