From 0a2a6c4db6a668a4b29763d04ccc48e212838913 Mon Sep 17 00:00:00 2001 From: Atreya Bain Date: Tue, 2 Jan 2024 17:15:19 +0530 Subject: [PATCH] [refactor] commands --- README.md | 32 ++++-- assets/screenshot.png | Bin 0 -> 28171 bytes client/src/BranFlakesExecutorVisitor.ts | 34 +++--- client/src/command/Command.ts | 5 + client/src/command/CompileCommand.ts | 26 +++++ client/src/extension.ts | 103 +++++++++--------- client/src/input/VSCodePromptInputStrategy.ts | 15 ++- package.json | 2 +- 8 files changed, 127 insertions(+), 90 deletions(-) create mode 100644 assets/screenshot.png create mode 100644 client/src/command/Command.ts create mode 100644 client/src/command/CompileCommand.ts diff --git a/README.md b/README.md index 1d9098f..77cf601 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,39 @@ # BF extension -A simple language server based VSCode Extension for the ~~Branflakes~~ BF language. You can also execute your code and see its output. +A simple language server based VSCode Extension for the (Branflakes?) (BrainFuck?) BF language. You can also execute your code and see its output. + +![BF](./assets/screenshot.png) -![BF](https://kekvrose.me/static/projects/screenshots/bf-server.png) ## Functionality -- [X] Syntax -- [X] Bracket matching -- [X] Autocomplete suggestions -- [X] Extension icon -- [X] Execution - - [ ] Timeout - - +- Syntax Highlighting +- Execution +- Autocomplete suggestions ### Execution Use the command to execute the code. -Issue is, because BF is a *turing complete* language, there is no way to know if the program will terminate or not. Hence for now, the command may lead to infinite execution. +Issue is, because BF is a **turing complete** language, there is no way to know if the program will terminate or not. Hence for now, the command may lead to infinite execution. If the program requires input, it will be requested as a prompt. TODO: Implement a timeout. ### Changelog +#### 0.2.0 + +- Cycle input pointer on overflow/underflow +- Refactoring code + #### 0.1.0 - Request input as required during execution -- Using array-based indexing. This implies that only positive indices upto 30k are supported. \ No newline at end of file +- Using array-based indexing. This implies that only positive indices upto 30k are supported. + + +### Building it + +1. `npm i` - Install all dependencies +2. `npm i -g @vscode/vsce` - Install VSCode Command line CLI +3. `vsce package` - Package to VSIX \ No newline at end of file diff --git a/assets/screenshot.png b/assets/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..609ea2cb5b800a9bb6776f43bbc92a9ffe9369d1 GIT binary patch literal 28171 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 Thenable, - protected inputPtr: number = 0 + private inputStrategy: InputStrategy, + private logger: (val: string) => Thenable, + private inputPtr: number = 0 ) { super(); } // /** // * The memory cells (Can work with negative cells this way) // */ - // protected cells: Map = new Map(); + // private cells: Map = new Map(); - protected byteArraySize: number = 30000; - protected byteArray: Int8Array = new Int8Array(this.byteArraySize); + private byteArraySize: number = 30000; + private byteArray: Int8Array = new Int8Array(this.byteArraySize); /** * Pointer */ - protected ptr: number = 0; + private ptr: number = 0; /** Output string */ - protected outputStrArray: string[] = []; + private outputStr: string = ''; - /** - * Output string (Available only after visiting) - */ - public get outputStr() { - return this.outputStrArray.join(''); - } + defaultResult() { return Promise.resolve(); @@ -57,7 +52,7 @@ export default class BranFlakesExecutorVisitor text: string, fn: string, inputStrategy: InputStrategy, - logger: (str:string) => Thenable + logger: (str: string) => Thenable ) { //get tree and issues const { tree, issues } = getTree(text, fn); @@ -90,10 +85,10 @@ export default class BranFlakesExecutorVisitor } } async visitPtrLeft() { - --this.ptr; + this.ptr = (this.ptr + this.byteArraySize - 1) % this.byteArraySize; } async visitPtrRight() { - ++this.ptr; + this.ptr = (this.ptr + this.byteArraySize + 1) % this.byteArraySize; } async visitPtrIncr() { const val = this.getCell(this.ptr); @@ -107,12 +102,12 @@ export default class BranFlakesExecutorVisitor const val = this.getCell(this.ptr) ?? 0; const str = String.fromCharCode(val); - this.outputStrArray.push(str); + this.outputStr += str; } async visitInputStmt() { //get char - const char = await this.inputStrategy.getInput() ?? 0; + const char = (await this.inputStrategy.getInput()) ?? 0; //increment the input pointer after this this.inputPtr++; this.setCell(this.ptr, char); @@ -120,7 +115,6 @@ export default class BranFlakesExecutorVisitor // override for maintaining async async visitChildren(node: RuleNode): Promise { - // await this.logger("checking "+node.constructor.name) let result = this.defaultResult(); await result; let n = node.childCount; diff --git a/client/src/command/Command.ts b/client/src/command/Command.ts new file mode 100644 index 0000000..da04d5d --- /dev/null +++ b/client/src/command/Command.ts @@ -0,0 +1,5 @@ + +export interface Command{ + getCommandName():string; + getCommandHandler():(...args:any)=>Promise; +} \ No newline at end of file diff --git a/client/src/command/CompileCommand.ts b/client/src/command/CompileCommand.ts new file mode 100644 index 0000000..d639080 --- /dev/null +++ b/client/src/command/CompileCommand.ts @@ -0,0 +1,26 @@ +import { window } from 'vscode'; +import { Command as BranFlakesCommand } from './Command'; +import { VSCodePromptInputStrategy } from '../input/VSCodePromptInputStrategy'; +import BranFlakesExecutorVisitor from '../BranFlakesExecutorVisitor'; + +export class CompileBranFlakesCommand implements BranFlakesCommand { + getCommandName() { + return 'bf.execute'; + } + getCommandHandler() { + return async () => { + const text = window.activeTextEditor.document.getText(); + const fn = window.activeTextEditor.document.fileName; + const inputStrategy = new VSCodePromptInputStrategy( + window.showInputBox + ); + const output = await BranFlakesExecutorVisitor.run( + text, + fn, + inputStrategy, + window.showInformationMessage + ); + await window.showInformationMessage(`Output: ${output}`); + }; + } +} diff --git a/client/src/extension.ts b/client/src/extension.ts index 2bd3f75..b1e4edb 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -4,71 +4,68 @@ * ------------------------------------------------------------------------------------------ */ import * as path from 'path'; -import { ExtensionContext,commands, window } from 'vscode'; +import { ExtensionContext, commands, window } from 'vscode'; import { - LanguageClient, - LanguageClientOptions, - ServerOptions, - TransportKind + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, } from 'vscode-languageclient'; -import BranFlakesExecutorVisitor from './BranFlakesExecutorVisitor'; -import { VSCodePromptInputStrategy } from './input/VSCodePromptInputStrategy'; - +import { CompileBranFlakesCommand } from './command/CompileCommand'; let client: LanguageClient; export function activate(context: ExtensionContext) { - // The server is implemented in node - let serverModule = context.asAbsolutePath( - path.join('server', 'dist', 'server.js') - ); - // The debug options for the server - // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging - let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] }; + // The server is implemented in node + let serverModule = context.asAbsolutePath( + path.join('server', 'dist', 'server.js') + ); + // The debug options for the server + // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging + let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] }; - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - let serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { - module: serverModule, - transport: TransportKind.ipc, - options: debugOptions - } - }; + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + options: debugOptions, + }, + }; - // Options to control the language client - let clientOptions: LanguageClientOptions = { - // Register the server for plain text documents - documentSelector: [{ scheme: 'file', language: 'bf' }] - }; + // Options to control the language client + let clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: 'file', language: 'bf' }], + }; - const command = 'bf.execute'; - const commandHandler = async()=>{ - const text= window.activeTextEditor.document.getText(); - const fn = window.activeTextEditor.document.fileName; - const inputStrategy = new VSCodePromptInputStrategy(window.showInputBox); - const output = await BranFlakesExecutorVisitor.run(text,fn,inputStrategy,window.showInformationMessage); - await window.showInformationMessage(`Output: ${output}`); - }; + const branFlakesCommands = [new CompileBranFlakesCommand()]; + for (let branFlakesCommand of branFlakesCommands) { + context.subscriptions.push( + commands.registerCommand( + branFlakesCommand.getCommandName(), + branFlakesCommand.getCommandHandler() + ) + ); + } - context.subscriptions.push(commands.registerCommand(command,commandHandler)); + // Create the language client and start the client. + client = new LanguageClient( + 'brainfucklanguageserver', + 'Brainfuck Language Server', + serverOptions, + clientOptions + ); - // Create the language client and start the client. - client = new LanguageClient( - 'brainfucklanguageserver', - 'Brainfuck Language Server', - serverOptions, - clientOptions - ); - - // Start the client. This will also launch the server - client.start(); + // Start the client. This will also launch the server + client.start(); } export function deactivate(): Thenable | undefined { - if (!client) { - return undefined; - } - return client.stop(); + if (!client) { + return undefined; + } + return client.stop(); } diff --git a/client/src/input/VSCodePromptInputStrategy.ts b/client/src/input/VSCodePromptInputStrategy.ts index ca084b8..cec77c2 100644 --- a/client/src/input/VSCodePromptInputStrategy.ts +++ b/client/src/input/VSCodePromptInputStrategy.ts @@ -2,8 +2,13 @@ import { CancellationToken, InputBoxOptions } from 'vscode'; import InputStrategy from './InputStrategy'; export class VSCodePromptInputStrategy implements InputStrategy { - private inputQueue:string; - constructor(private requestor:(promptOptions?:InputBoxOptions,cancelToken?:CancellationToken)=>Thenable) {} + private inputQueue: string = ''; + constructor( + private requestor: ( + promptOptions?: InputBoxOptions, + cancelToken?: CancellationToken + ) => Thenable + ) {} async getInput(): Promise { while (this.inputQueue.length == 0) { @@ -11,11 +16,13 @@ export class VSCodePromptInputStrategy implements InputStrategy { } const character = this.inputQueue.charCodeAt(0); this.inputQueue = this.inputQueue.substring(1); - + return character; } private async requestInputFromPrompt() { - const inputPrompt = await this.requestor({prompt:"More input is required. Please provide input:"}); + const inputPrompt = await this.requestor({ + prompt: 'More input is required. Please provide input:', + }); this.inputQueue += inputPrompt; } } diff --git a/package.json b/package.json index e9d75f3..449743f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "author": "Atreya Bain", "license": "MIT", "publisher": "atreyabain", - "version": "0.1.0", + "version": "0.2.0", "icon": "assets/128.png", "categories": [], "keywords": [