Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/coolbutuseless/rbytecode
R bytecode assembler/disassembler
https://github.com/coolbutuseless/rbytecode
bytecode r
Last synced: 3 months ago
JSON representation
R bytecode assembler/disassembler
- Host: GitHub
- URL: https://github.com/coolbutuseless/rbytecode
- Owner: coolbutuseless
- License: other
- Created: 2023-10-24T10:04:53.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-08-09T04:02:18.000Z (5 months ago)
- Last Synced: 2024-10-12T21:24:48.429Z (3 months ago)
- Topics: bytecode, r
- Language: R
- Homepage: https://coolbutuseless.github.io/book/rbytecodebook/
- Size: 706 KB
- Stars: 35
- Watchers: 5
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
- Changelog: NEWS.md
- License: LICENSE
Awesome Lists containing this project
README
---
output: github_document
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = FALSE,
comment = "",
fig.path = "man/figures/README-",
out.width = "100%"
)library(rbytecode)
```# rbytecode
![](https://img.shields.io/badge/cool-useless-green.svg)
Modern R now executes most code in a stack-based virtual machine (VM).
The R code you write is first parsed to
an abstract syntax tree, which is then compiled to bytecode, and this
bytecode is then executed in *R's bytecode VM*.`{rbytecode}` provides an assembler and disassembler for R bytecode - allowing
you to peek under the hood at what R is doing to execute your code.The disassembler is a way of inspecting R code internals by dissecting existing code.
The assembler is a way of compiling R *bytecode assembly* directly into a *bytecode object* i.e.
writing directly in the virtual machine language understood internally by
R's bytecode VM.This work is heavily based around the `{compiler}` package (built-in to R) and
Luke Tierney's document
[A Byte Code Compiler for R](https://homepage.cs.uiowa.edu/~luke/R/compiler/compiler.pdf)## This package has a book!
I have written a book to accompany this package. The book gives some background on
R's execution of code in its stack-based virtual machine and a reference for the
different bytecode instructions understood by this VM.Available from:
* [LeanPub](https://leanpub.com/rbytecode) EPUB available for free - but
if you felt like showing support there is an option for a small payment.
* [Online html](https://coolbutuseless.github.io/book/rbytecodebook/)# Ideas for the Future
* Add support for `SWITCH` instruction
* Keep track of stack size during assembly to try and catch bad code.
* Write a small VM - maybe only covering a subset of instructions.## What's in the box
* `dis()` disassembles R language objects to bytecode assembly
* `disq()` a helper function where `disq(1 + x)` is equivalent to `dis(quote(1 + x))`
* `asm()` an assembler for R bytecode. Takes R bytecode assembly and outputs
an executable bytecode object## Installation
You can install from [GitHub](https://github.com/coolbutuseless/rbytecode) with:
``` r
# install.package('remotes')
remotes::install_github('coolbutuseless/rbytecode')
```## Disassembler
```{r example}
library(rbytecode)disq(x + 1) |>
as.character()
``````{r}
disq(function(x, y = 1) {x + y}) |>
as.character()
```## Assembler - simple example
```{r}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create bytecode assembly
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
code <- r"(
LDCONST 1
LDCONST 2
ADD
RETURN
)"#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assemble the code into a bytecode object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bc <- asm(code)
bc#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Evaluate the bytecode
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eval(bc)
```## Bytecode Assembly - Fibonacci
The following bytecode assembly is a reimplementation of R code for calculating
the 11th Fibonacci number.```{r}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# R implementation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
i <- 0
fn2 <- 0
fn1 <- 1
while (i < 10) {
fnnew <- fn1 + fn2
fn2 <- fn1
fn1 <- fnnew
i <- i + 1
}
fn1
``````{r}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Bytecode implementation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
code <- r"(
LDCONST 0L
SETVAR i
SETVAR fn2
LDCONST 1L
SETVAR fn1
@start
GETVAR i
LDCONST 10L
LT
BRIFNOT @end
GETVAR fn1
GETVAR fn2
ADD
SETVAR fnnew
POP
GETVAR fn1
SETVAR fn2
POP
GETVAR fnnew
SETVAR fn1
POP
GETVAR i
LDCONST 1L
ADD
SETVAR i
POP
GOTO @start
@end
GETVAR fn1
RETURN
)"asm(code) |> eval()
```## Related Software
* The `{compiler}` package. One of the base R packages.
## Acknowledgements
* R Core for developing and maintaining the language.
* CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository