Repository: wolfgang42/rockstar-js
Branch: master
Commit: 29a14768db98
Files: 15
Total size: 19.4 KB
Directory structure:
gitextract_6u9na67n/
├── .gitignore
├── LICENSE
├── README.md
├── examples/
│ ├── fizzbuzz-idiomatic.out.txt
│ ├── fizzbuzz-idiomatic.rock
│ ├── fizzbuzz-minimalist.out.txt
│ ├── fizzbuzz-minimalist.rock
│ ├── listen.rock
│ ├── treesort.out.txt
│ └── treesort.rock
├── package.json
├── rockstar
├── src/
│ ├── rockstar-parser.peg
│ └── rockstar.js
└── test/
└── integration.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules/
examples/*.js
rockstar-parser.js
package-lock.json
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Wolfgang Faust
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
This is a work-in-progress implementation of the [Rockstar](https://github.com/dylanbeattie/rockstar) language.
It transpiles Rockstar code to JavaScript.
Usage:
```
yarn install
./rockstar program.rock
node program.js
```
**Note:** Due to the extremely fast speed of updates to Rockstar, this implementation may not always match the current spec. [wolfgang42/rockstar](https://github.com/wolfgang42/rockstar) has the version of this spec targeted by this implementation. View differences between the two here: [wolfgang42/master...dylanbeattie/master](https://github.com/wolfgang42/rockstar/compare/master...dylanbeattie:master)
Also, since this is a WIP not all of Rockstar works properly yet. See the [Spec Complete milestone](https://github.com/wolfgang42/rockstar-js/milestone/1) for the list of unimplemented features.
Contributions welcome!
# Design
Transpilation is broken up into three stages: parsing, block grouping, and code generation.
## Parsing
First, the text of the program is parsed into statements and expressions. The resulting tokens are objects which have a `t` property containing the type of the token, plus other properties (generally a single mnemonic letter) with additional information about the token.
Parsing is currently implemented using [PEG.js](https://pegjs.org/), a JS Parser Generator. I'm not entirely convinced that this was the best choice but it seems to work OK so far.
For example, the poetic string literal:
```
Billy says hello world!
```
is parsed by this expression:
```
PoeticString = v:Variable _ 'says' ' ' t:$[^\n]*
{ return {t: 'Set', v: v, e: {t: 'Literal', v: t}} }
```
into this token:
```javascript
{t: "Set", v: {t: "Variable", n: "Billy"}, e: {t: "Literal", v: "hello world!"}}
```
(Notice that this token contains two other tokens, `v` and `e`.)
**Note for developers:** After changing `rockstar-parser.peg`, make sure you run `yarn build` to regenerate the parser code.
## Block grouping
The parsing step returns a series of statements, but does not know about blocks. This step (implemented by the `groupBlocks` function) finds statements which begin blocks (`If`, `While`, and so on) and groups the statements together inside a `Block` token, removing `BlankLine` tokens.
## Code generation
This stage takes the tokens and emits JavaScript code. Each token has a function in the `generators` object which takes a token and returns a string. Many of these operate recursively, calling `expr()` on a token to generate code to be included.
For example, the `Set` token generator:
```javascript
Set: s => `${expr(s.v)}=${expr(s.e)};`,
```
takes a Token like this:
```javascript
{t: "Set", v: {t: "Variable", n: "Billy"}, e: {t: "Literal", v: "hello world!"}}
```
and returns this code:
```javascript
Billy="hello world!";
```
================================================
FILE: examples/fizzbuzz-idiomatic.out.txt
================================================
1
2
Fizz!
4
Buzz!
Fizz!
7
8
Fizz!
Buzz!
11
Fizz!
13
14
FizzBuzz!
16
17
Fizz!
19
Buzz!
Fizz!
22
23
Fizz!
Buzz!
26
Fizz!
28
29
FizzBuzz!
31
32
Fizz!
34
Buzz!
Fizz!
37
38
Fizz!
Buzz!
41
Fizz!
43
44
FizzBuzz!
46
47
Fizz!
49
Buzz!
Fizz!
52
53
Fizz!
Buzz!
56
Fizz!
58
59
FizzBuzz!
61
62
Fizz!
64
Buzz!
Fizz!
67
68
Fizz!
Buzz!
71
Fizz!
73
74
FizzBuzz!
76
77
Fizz!
79
Buzz!
Fizz!
82
83
Fizz!
Buzz!
86
Fizz!
88
89
FizzBuzz!
91
92
Fizz!
94
Buzz!
Fizz!
97
98
Fizz!
Buzz!
================================================
FILE: examples/fizzbuzz-idiomatic.rock
================================================
Midnight takes your heart and your soul
While your heart is as high as your soul
Put your heart without your soul into your heart
Give back your heart
Desire is a lovestruck ladykiller
My world is nothing
Fire is ice
Hate is water
Until my world is Desire,
Build my world up
If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing
Shout "FizzBuzz!"
Take it to the top
If Midnight taking my world, Fire is nothing
Shout "Fizz!"
Take it to the top
If Midnight taking my world, Hate is nothing
Say "Buzz!"
Take it to the top
Whisper my world
================================================
FILE: examples/fizzbuzz-minimalist.out.txt
================================================
1
2
Fizz!
4
Buzz!
Fizz!
7
8
Fizz!
Buzz!
11
Fizz!
13
14
FizzBuzz!
16
17
Fizz!
19
Buzz!
Fizz!
22
23
Fizz!
Buzz!
26
Fizz!
28
29
FizzBuzz!
31
32
Fizz!
34
Buzz!
Fizz!
37
38
Fizz!
Buzz!
41
Fizz!
43
44
FizzBuzz!
46
47
Fizz!
49
Buzz!
Fizz!
52
53
Fizz!
Buzz!
56
Fizz!
58
59
FizzBuzz!
61
62
Fizz!
64
Buzz!
Fizz!
67
68
Fizz!
Buzz!
71
Fizz!
73
74
FizzBuzz!
76
77
Fizz!
79
Buzz!
Fizz!
82
83
Fizz!
Buzz!
86
Fizz!
88
89
FizzBuzz!
91
92
Fizz!
94
Buzz!
Fizz!
97
98
Fizz!
Buzz!
================================================
FILE: examples/fizzbuzz-minimalist.rock
================================================
Modulus takes Number and Divisor
While Number is as high as Divisor
Put Number minus Divisor into Number
(blank line ending While block)
Give back Number
(blank line ending function declaration)
Limit is 100
Counter is 0
Fizz is 3
Buzz is 5
Until Counter is Limit
Build Counter up
If Modulus taking Counter, Fizz is 0 and Modulus taking Counter, Buzz is 0
Say "FizzBuzz!"
Continue
(blank line ending 'If' Block)
If Modulus taking Counter and Fizz is 0
Say "Fizz!"
Continue
(blank line ending 'If' Block)
If Modulus taking Counter and Buzz is 0
Say "Buzz!"
Continue
(blank line ending 'If' Block)
Say Counter
(EOL ending Until block)
================================================
FILE: examples/listen.rock
================================================
Listen to my voice
Build my voice up
Scream my voice
================================================
FILE: examples/treesort.out.txt
================================================
822
4805
9117
10097
10402
13586
20636
24037
24805
32533
34673
37542
39292
54876
64894
74296
74945
76520
80959
91665
================================================
FILE: examples/treesort.rock
================================================
Nodeoperationread is 0
Nodeoperationwrite is 1
Nodevalueignored is 0
Nodevariablevalue is 0
Nodevariableleft is 1
Nodevariableright is 2
Makenode takes Value, Left, Right
Node takes Operation, Variable, Newvalue
If Operation is Nodeoperationread
If Variable is Nodevariablevalue
Give back Value
(end if)
If Variable is Nodevariableleft
Give back Left
(end if)
If Variable is Nodevariableright
Give back Right
(end if)
(end if)
If Operation is Nodeoperationwrite
If Variable is Nodevariablevalue
Put Newvalue into Value
(end if)
If Variable is Nodevariableleft
Put Newvalue into Left
(end if)
If Variable is Nodevariableright
Put Newvalue into Right
(end if)
(end if)
(end function)
Give back Node
(end function)
Insertnode takes Node, Newvalue
Put Makenode taking Newvalue, nothing, nothing into Newnode
If Node is nothing
Give back Newnode
(end if)
Put Node into Originalroot
Put nothing into Parentnode
Put Nodevariableright into Direction
While Node is not nothing
Put Node taking Nodeoperationread, Nodevariablevalue, Nodevalueignored into Value
Put Nodevariableright into Direction
If Newvalue is less than Value
Put Nodevariableleft into Direction
(end if)
Put Node into Parentnode
Put Node taking Nodeoperationread, Direction, Nodevalueignored into Node
(end while)
Put Parentnode taking Nodeoperationwrite, Direction, Newnode into Unusedreturnvalue
Give back Originalroot
(end function)
Inorder takes Node
If Node is nothing
Give back nothing
(end if)
Put Node taking Nodeoperationread, Nodevariableleft, Nodevalueignored into Left
Put Inorder taking Left into Unusedreturnvalue
Put Node taking Nodeoperationread, Nodevariablevalue, Nodevalueignored into Value
Say Value
Put Node taking Nodeoperationread, Nodevariableright, Nodevalueignored into Right
Put Inorder taking Right into Unusedreturnvalue
Give back nothing
(end function)
Main takes Root
Put Insertnode taking Root, 10097 into Root
Put Insertnode taking Root, 32533 into Root
Put Insertnode taking Root, 76520 into Root
Put Insertnode taking Root, 13586 into Root
Put Insertnode taking Root, 34673 into Root
Put Insertnode taking Root, 54876 into Root
Put Insertnode taking Root, 80959 into Root
Put Insertnode taking Root, 9117 into Root
Put Insertnode taking Root, 39292 into Root
Put Insertnode taking Root, 74945 into Root
Put Insertnode taking Root, 37542 into Root
Put Insertnode taking Root, 4805 into Root
Put Insertnode taking Root, 64894 into Root
Put Insertnode taking Root, 74296 into Root
Put Insertnode taking Root, 24805 into Root
Put Insertnode taking Root, 24037 into Root
Put Insertnode taking Root, 20636 into Root
Put Insertnode taking Root, 10402 into Root
Put Insertnode taking Root, 822 into Root
Put Insertnode taking Root, 91665 into Root
Put Inorder taking Root into Unusedreturnvalue
(end function)
Put Main taking nothing into Unusedreturnvalue
================================================
FILE: package.json
================================================
{
"name": "rockstar-js",
"version": "0.0.1",
"description": "JavaScript transpiler for the esoteric language 'Rockstar'",
"homepage": "https://github.com/wolfgang42/rockstar-js",
"bugs": "https://github.com/wolfgang42/rockstar-js/issues",
"repository": "github:wolfgang42/rockstar-js",
"license": "MIT",
"author": "Wolfgang Faust",
"main": "src/rockstar.js",
"bin": "./rockstar",
"directories": {
"lib": "src/",
"example": "examples/"
},
"dependencies": {},
"devDependencies": {
"mocha": "^5.2.0",
"pegjs": "^0.10.0"
},
"scripts": {
"build": "pegjs src/rockstar-parser.peg",
"test": "mocha",
"prepublish": "npm run build"
}
}
================================================
FILE: rockstar
================================================
#!/usr/bin/env node
const rockstar = require('./src/rockstar')
const fs = require('fs')
function promisify(fn, ...args) {
return new Promise((resolve, reject) => fn(...args, (err, result) => {
if (err) {
reject(err)
} else {
resolve(result)
}
}))
}
const filename = process.argv[2]
promisify(fs.readFile, filename, 'utf-8')
.then(rockstar.compile)
.then(code => promisify(fs.writeFile, filename.replace('.rock', '.js'), code))
.then(null, e => {
console.error(e)
process.exit(1)
})
================================================
FILE: src/rockstar-parser.peg
================================================
Program = Statement *
Statement = _? s:(FunctionDeclaration/Operation/BlankLine) ','? _* '\n' {return s}
Operation = Loop / If / ArithmeticStatement / GiveBack / Set / Put / Listen / Say / Continue / Break / PoeticString
_ = ((' ' / '\t')+) / Comment
Comment = '(' [^)]* ')'
Variable =
(n:(CommonVariable / ProperVariable) {return {t: 'Variable', n}})
/ Pronoun {return {t: 'Pronoun'}}
CommonVariable = p:('the'i/'my'i/'your'i) _ v:$([a-z]+) {return p+v}
ProperWord = $([A-Z][A-Za-z]+)
ProperVariable = $(ProperWord _ ProperVariable) / $ProperWord
Pronoun = (
'it'i
/'he'i/'she'i/'him'i/'her'i
/'them'i/'they'i
/'ze'i/'hir'i/'zie'i/'zir'i/'xe'i/'xem'i/'ve'i/'ver'i
)
TypeLiteral = v:TypeLiteralValue { return {t: 'Literal', v} }
TypeLiteralValue =
('nothing'/'nobody'/'nowhere'/'empty'/'gone') {return 0} // TODO null?
/ ('true'/'right'/'yes'/'ok') {return true}
/ ('false'/'wrong'/'no'/'lies') {return false}
/ 'mysterious' { return undefined}
String = '"' v:$[^"]+ '"'
{ return {t: 'Literal', v}}
Number = n:$([0-9]+ ('.' [0-9]+)?)
{ return {t: 'Literal', v: parseFloat(n)} }
ArithmeticStatement = BuildUp / KnockDown
BuildUp = 'Build' _ v:Variable _ 'up'
{ return {t: 'Rement', v: v, o: '++'} }
KnockDown = 'Knock' _ v:Variable _ 'down'
{ return {t: 'Rement', v: v, o: '--'} }
PoeticString = v:Variable _ 'says' ' ' t:$[^\n]*
{ return {t: 'Set', v: v, e: {t: 'Literal', v: t}} }
PoeticNumber = n:PoeticDigits d:PoeticDecimal? {return {t: 'Literal', v: parseFloat(d?n+'.'+d:n)}}
PoeticDecimal = '.' _ d:PoeticDigits {return d}
PoeticDigits =
l:PoeticDigit ( _ / [\',;:?!] )+ r:PoeticDigits { return l+r }
/ d: PoeticDigit { return d }
PoeticDigit = t:[A-Za-z]+ {return (t.length%10).toString()}
ArithmeticExpression =
l:SimpleExpression
_ o:ArithmeticOperator _
r:SimpleExpression
{ return {t: 'Arithmetic', l, o, r} }
ArithmeticOperator =
('minus'/'without') {return '-'}
/ ('plus'/'with') {return '+'}
/ ('times'/'of') {return '*'}
/ ('over') {return '/'}
Comparison = l:SimpleExpression _ b:BoolCheck c:Comparator? r:SimpleExpression
{ return {t: 'Comparison', l, r, b, c} }
BoolCheck =
(('is'_'not'_)/"ain't"_) { return false }
/ 'is'_ { return true }
Comparator =
('higher'/'greater'/'bigger'/'stronger')_'than'_ { return 'gt' }
/ ('lower'/'less'/'smaller'/'weaker')_'than'_ { return 'lt' }
/ 'as'_('high'/'great'/'big'/'strong')_'as'_ {return 'ge'}
/ 'as'_('low'/'little'/'small'/'weak')_'as'_ {return 'le'}
Listen = 'Listen' _ 'to' _ v:Variable
{return {t:'Listen', v}}
Say = ('Say'/'Shout'/'Whisper'/'Scream') _ e:Expression
{return {t:'Say', e}}
If = 'If' _ e:Expression
{ return {t: 'If', e} }
Else = 'Else' {return {t: 'Else'}}
Loop = c:('While'/'Until') _ e:Expression
{ return {t: 'Loop', c, e} }
Continue = ('Continue' / ('Take'_'it'_'to'_'the'_'top')) {return {t: 'Continue'}}
Break = ('Break' / ('Break'_'it'_'down')) {return {t: 'Break'}}
FunctionDeclaration = n:Variable _ 'takes' _ a:FunctionDeclarationArguments
{ return {t: 'FunctionDeclaration', n, a: a.map(a => a.n)} }
FunctionDeclarationArguments =
a:Variable (_'and'_ / _?','_?) b:FunctionDeclarationArguments { return [a].concat(b) }
/ a:Variable { return [a] }
GiveBack = 'Give back' _ e:Expression
{ return {t: 'GiveBack', e} }
BlankLine = '' {return {t: 'BlankLine'}}
FunctionCall = f:Variable _ 'taking' _ a:FunctionCallArguments
{ return {t: 'FunctionCall', f, a} }
// TODO 'and' is overloaded, so can't use full Expression syntax
FunctionCallArguments =
a:SimpleExpression (_'and'_ / _?','_?) b:FunctionCallArguments { return [a].concat(b) }
/ a:SimpleExpression { return [a] }
///////////////////////
// TODO Everything below here is never explicitly defined in the spec
Expression = ArithmeticExpression / BooleanOperation
SimpleExpression = FunctionCall / TypeLiteral / Variable / Number / String / PoeticNumber
BooleanOperation =
(
l:(Comparison / SimpleExpression)
_ b:('and'/'or') _
r:Expression
{ return {t: 'BooleanOperation', l, b, r} }
)
/ l: (Comparison / SimpleExpression) { return l }
Set = v:Variable _ ('is'/'was'/'were') _ e:Expression
{ return {t: 'Set', v: v, e} }
Put = 'Put' _ e:Expression _ 'into' _ v:Variable
{ return {t: 'Set', v: v, e} }
================================================
FILE: src/rockstar.js
================================================
const parser = require('./rockstar-parser')
let it
const generators = {
Block: b => `{${b.s.map(expr).join('')}}`,
FunctionDeclaration: f => `function ${expr(f.n)}(${f.a.map(varname).join(',')})`,
FunctionCall: f => `${expr(f.f)}(${f.a.map(expr).join(',')})`,
Loop: w => {
let cond = expr(w.e)
if (w.c === 'Until') cond = `!(${cond})`
return `while(${cond})`
},
Continue: _ => 'continue;',
Break: _ => 'break;',
If: i => `if(${expr(i.e)})`,
Else: _ => 'else',
Comparison: c => {
let ret = expr(c.l)
if (c.c) {
const comp = {
gt: '>',
lt: '<',
ge: '>=',
le: '<=',
}
ret += comp[c.c]
} else {
if (c.b) {
ret += '==='
} else {
ret += '!=='
}
}
ret += expr(c.r)
if (!c && !b) ret = `!(${ret})`
return ret
},
BooleanOperation: b => `${expr(b.l)}${b.b=='and'?'&&':'||'}${expr(b.r)}`,
Variable: v => {
it = v
return varname(v.n)
},
Pronoun: p => expr(it),
Rement: r => `${expr(r.v)}${r.o};`,
Arithmetic: a => `${expr(a.l)}${a.o}${expr(a.r)}`,
Set: s => `${expr(s.v)}=${expr(s.e)};`,
Literal: l => JSON.stringify(l.v),
GiveBack: g => `return ${expr(g.e)};`,
Say: s=>`console.log(${expr(s.e)});`,
Listen: ({ v }) => `${varname(v.n)} = $readLineSync();`
}
const dependencies = {
addReadLine: `
function $readLineSync() {
const line = [];
const buffer = Buffer.alloc(1);
while (true) {
const bytes = $fs.readSync(1, buffer, 0, 1, null);
if (!bytes) break;
if (buffer[0] === 10 || buffer[0] === 13) break;
line.push(buffer[0]);
}
return Buffer.from(line).toString('utf-8');
}
`,
fs: `const $fs = require('fs');`,
}
function varname(v) {
return v.replace(/ /g, '')
}
function expr(e) {
if (!(e.t in generators)) {
console.log(e)
throw new Error('Unknown statement type: '+e.t)
}
return generators[e.t](e)
}
function _groupBlocks(statements) {
let ret = []
let stmt
while (stmt = statements.shift()) {
if (stmt.t == 'BlankLine') return ret
ret.push(stmt)
if (stmt.t == 'If' || stmt.t == 'Else' || stmt.t == 'Loop' || stmt.t == 'FunctionDeclaration') {
ret.push({
t: 'Block',
s: _groupBlocks(statements),
})
}
}
return ret
}
function groupBlocks(statements) {
const ret = []
while (statements.length !== 0) {
_groupBlocks(statements).forEach(s => ret.push(s))
}
return ret
}
function computeDependencies(statements) {
const deps = [];
if (statements.some(s => s.t === 'Listen')) {
deps.push('fs', 'addReadLine');
}
// TODO: (eventually) remove dup `deps`
return deps;
}
function generateDependencies(deps) {
return deps.map(d => dependencies[d]);
}
function parse(programText) {
// Parser requires newline before EOF, add it in case there wasn't one already.
return parser.parse(programText+'\n')
}
function compile(programText) {
const statements = parse(programText)
const dependencies = generateDependencies(computeDependencies(statements));
const program = groupBlocks(statements)
return [
...dependencies,
...program.map(expr)
].join('')
}
module.exports = {
varname,
expr,
groupBlocks,
parse,
compile,
computeDependencies,
generateDependencies,
}
================================================
FILE: test/integration.js
================================================
const test_examples = [
'fizzbuzz-idiomatic',
'fizzbuzz-minimalist',
'listen',
'treesort',
]
const rockstar = require('../src/rockstar')
const fs = require('fs')
const child_process = require('child_process')
function promisify(fn, ...args) {
return new Promise((resolve, reject) => fn(...args, (...result) => resolve(result)))
}
async function promisify_one(fn, ...args) {
const r = await promisify(fn, ...args)
if (r.length !== 1) throw new Error('promisify_one called with returning '+r.length+' args')
return r[0]
}
async function promisify_err(fn, ...args) {
const r = await promisify(fn, ...args)
if (r.length !== 2) throw new Error('promisify_one called with returning '+r.length+' args')
if (r[0]) throw r[0]
return r[1]
}
const readFile = filename => promisify_err(fs.readFile, filename, 'utf-8')
const fileExists = filename => promisify_one(fs.exists, filename)
function runJs(code) {
return new Promise((resolve, reject) => {
let output = ''
const node = child_process.spawn('node')
node.stdout.on('data', data => output += data)
node.on('close', () => resolve(output))
node.stdin.end(code)
})
}
describe('Examples', () => {
test_examples.forEach(example => it(example, async () => {
example = `${__dirname}/../examples/${example}`
const rsCode = await readFile(example+'.rock')
const jsCode = rockstar.compile(rsCode)
if (await fileExists(example+'.out.txt')) {
const expectOutput = await readFile(example+'.out.txt')
const realOutput = await runJs(jsCode)
if (expectOutput != realOutput) throw new Error('Actual output does not match expected output')
}
}))
})
gitextract_6u9na67n/
├── .gitignore
├── LICENSE
├── README.md
├── examples/
│ ├── fizzbuzz-idiomatic.out.txt
│ ├── fizzbuzz-idiomatic.rock
│ ├── fizzbuzz-minimalist.out.txt
│ ├── fizzbuzz-minimalist.rock
│ ├── listen.rock
│ ├── treesort.out.txt
│ └── treesort.rock
├── package.json
├── rockstar
├── src/
│ ├── rockstar-parser.peg
│ └── rockstar.js
└── test/
└── integration.js
SYMBOL INDEX (12 symbols across 2 files)
FILE: src/rockstar.js
function varname (line 70) | function varname(v) {
function expr (line 74) | function expr(e) {
function _groupBlocks (line 82) | function _groupBlocks(statements) {
function groupBlocks (line 97) | function groupBlocks(statements) {
function computeDependencies (line 105) | function computeDependencies(statements) {
function generateDependencies (line 114) | function generateDependencies(deps) {
function parse (line 118) | function parse(programText) {
function compile (line 123) | function compile(programText) {
FILE: test/integration.js
function promisify (line 12) | function promisify(fn, ...args) {
function promisify_one (line 15) | async function promisify_one(fn, ...args) {
function promisify_err (line 20) | async function promisify_err(fn, ...args) {
function runJs (line 29) | function runJs(code) {
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (22K chars).
[
{
"path": ".gitignore",
"chars": 64,
"preview": "node_modules/\nexamples/*.js\nrockstar-parser.js\npackage-lock.json"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2018 Wolfgang Faust\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "README.md",
"chars": 2798,
"preview": "This is a work-in-progress implementation of the [Rockstar](https://github.com/dylanbeattie/rockstar) language.\n\nIt tran"
},
{
"path": "examples/fizzbuzz-idiomatic.out.txt",
"chars": 460,
"preview": "1\n2\nFizz!\n4\nBuzz!\nFizz!\n7\n8\nFizz!\nBuzz!\n11\nFizz!\n13\n14\nFizzBuzz!\n16\n17\nFizz!\n19\nBuzz!\nFizz!\n22\n23\nFizz!\nBuzz!\n26\nFizz!\n2"
},
{
"path": "examples/fizzbuzz-idiomatic.rock",
"chars": 581,
"preview": "Midnight takes your heart and your soul\nWhile your heart is as high as your soul\nPut your heart without your soul into y"
},
{
"path": "examples/fizzbuzz-minimalist.out.txt",
"chars": 460,
"preview": "1\n2\nFizz!\n4\nBuzz!\nFizz!\n7\n8\nFizz!\nBuzz!\n11\nFizz!\n13\n14\nFizzBuzz!\n16\n17\nFizz!\n19\nBuzz!\nFizz!\n22\n23\nFizz!\nBuzz!\n26\nFizz!\n2"
},
{
"path": "examples/fizzbuzz-minimalist.rock",
"chars": 657,
"preview": "Modulus takes Number and Divisor\nWhile Number is as high as Divisor\nPut Number minus Divisor into Number\n (blank line"
},
{
"path": "examples/listen.rock",
"chars": 53,
"preview": "Listen to my voice\nBuild my voice up\nScream my voice\n"
},
{
"path": "examples/treesort.out.txt",
"chars": 116,
"preview": "822\n4805\n9117\n10097\n10402\n13586\n20636\n24037\n24805\n32533\n34673\n37542\n39292\n54876\n64894\n74296\n74945\n76520\n80959\n91665\n"
},
{
"path": "examples/treesort.rock",
"chars": 3363,
"preview": "Nodeoperationread is 0\nNodeoperationwrite is 1\nNodevalueignored is 0\nNodevariablevalue is 0\nNodevariableleft is 1\nNodeva"
},
{
"path": "package.json",
"chars": 688,
"preview": "{\n \"name\": \"rockstar-js\",\n \"version\": \"0.0.1\",\n \"description\": \"JavaScript transpiler for the esoteric language 'Rock"
},
{
"path": "rockstar",
"chars": 501,
"preview": "#!/usr/bin/env node\nconst rockstar = require('./src/rockstar')\nconst fs = require('fs')\n\nfunction promisify(fn, ...args)"
},
{
"path": "src/rockstar-parser.peg",
"chars": 4272,
"preview": "Program = Statement *\nStatement = _? s:(FunctionDeclaration/Operation/BlankLine) ','? _* '\\n' {return s}\nOperation = Loo"
},
{
"path": "src/rockstar.js",
"chars": 3143,
"preview": "const parser = require('./rockstar-parser')\n\nlet it\nconst generators = {\n\tBlock: b => `{${b.s.map(expr).join('')}}`,\n\tFu"
},
{
"path": "test/integration.js",
"chars": 1623,
"preview": "const test_examples = [\n\t'fizzbuzz-idiomatic',\n\t'fizzbuzz-minimalist',\n\t'listen',\n\t'treesort',\n]\n\nconst rockstar = requi"
}
]
About this extraction
This page contains the full source code of the wolfgang42/rockstar-js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (19.4 KB), approximately 6.1k tokens, and a symbol index with 12 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.