<commit_before># JSCPP

This is a simple C++ interpreter written in JavaScript.

Try it out [on github.io](https://felixhao28.github.io/JSCPP/)!

## Purpose of the project

As far as I know, every public online C++ excuting environment requires backend servers to compile and run the produced executable. A portable and lightweight interpreter that can be run in browsers can be a fine substitute for those who do not intend to pay for such services.

I also want to make a strict interpreter. The reason being C++ has too many undefined and platform-dependent behaviors and popular C++ compilers tend to be an "over-caring mother" who tries to ignore or even justify the undocumented usages. The abuse of them should be avoided as much as possible IMO. For example, I do not want my students to take it as guaranteed that `sizeof int` produces `4`, because on Arduino Uno, an `int` is a 2-byte value.

Currently, it is mainly for educational uses for a MOOC course I am running (and fun).

## Prerequisites

* NodeJS or
* A modern browser

## How to use

Installation

```
npm install JSCPP
```

or (to use lastest cutting-edge version or to contribute)

```
git clone https://github.com/felixhao28/JSCPP.git
cd JSCPP
npm install .
```

### With NodeJS

Use __launcher.run__

```js
var JSCPP = require('JSCPP');
var launcher = JSCPP.launcher;
var code =    "#include <iostream>"    + "\n"
            + "using namespace std;"   + "\n"
            + "int main() {"           + "\n"
            + "    int a;"             + "\n"
            + "    cin >> a;"          + "\n"
            + "    cout << a << endl;" + "\n"
            + "    return 0;"          + "\n"
            + "}"                      + "\n"
;
var input = '4321';
var exitcode = launcher.run(code, input);
console.info('program exited with code ' + exitcode);
```

See _demo/example.coffee_ for example.

Or do it step by step:

Configuring standard IO and libraries
```js
var JSCPP = require('JSCPP');
var Runtime = JSCPP.Runtime;
var inputbuffer = "1 2 3";
var rt = new Runtime({
	stdio: {
		drain: function() {
			// This method will be called when program requires additional input
			// so you can return "1", "2" and "3" seperately during three calls.
			// Returning null value means EOF.
			var x = inputbuffer;
			inputbuffer = null;
			return x;
		},
		write: function(s) {
			process.stdout.write(s);
		}
	},
	includes: {
		iostream: require('./includes/iostream'),
		cmath: require('./includes/cmath')
		// Of course you can add more libraries here.
		// These libraries are only made available for "include" to happen
		// and NOT ready to be used in your cpp code.
		// You should use proper include directive to include them
		// or call load method on them directly (shown below).
	}
});
```

Using preprocessor (experimental)
```js
var preprocessor = JSCPP.preprocessor;
console.log('preprocessing starting');
code = preprocessor(rt, prepast, code);
console.log('preprocessing finished');
```

(Optional) If you choose not to use preprocessor, directives like `#include <...>` will not work, you need to load libraries manually
```js
rt.config.includes.iostream.load(rt);
rt.config.includes.cmath.load(rt);
```

Building AST
```js
var ast = JSCPP.ast;
var tree = ast.parse(code);
console.log('passed syntax check');
```

Interpreting AST (from global main function)
```js
var Interpreter = JSCPP.Interpreter;
var interpreter = new Interpreter(rt);
interpreter.run(tree);
var exitCode = rt.getFunc('global', 'main', [])(rt, null, []).v;
console.info('program exited with code ' + exitCode);
```

A full example is available in *demo/verbose_example.coffee*.

Use __debugger__

Unlike most other IDE, the debugging here is actually a replay of the execution.

```js
var mydebugger = new JSCPP.Debugger();
var exitCode = JSCPP.launcher.run(code, input, {debug: true, debugger: mydebugger});
// continue to the next statement
var hasNext = mydebugger.next();
if (!hasNext) {
	console.log("program exited with code " + exitCode);
}
// go back to the previous statement
var hasPrev = mydebugger.prev();
// examine the content of the output window
var outputContent = mydebugger.output();
// the content of the statement to be executed next<commit_msg>unify quote marks<commit_after># JSCPP

This is a simple C++ interpreter written in JavaScript.

Try it out [on github.io](https://felixhao28.github.io/JSCPP/)!

## Purpose of the project

As far as I know, every public online C++ excuting environment requires backend servers to compile and run the produced executable. A portable and lightweight interpreter that can be run in browsers can be a fine substitute for those who do not intend to pay for such services.

I also want to make a strict interpreter. The reason being C++ has too many undefined and platform-dependent behaviors and popular C++ compilers tend to be an "over-caring mother" who tries to ignore or even justify the undocumented usages. The abuse of them should be avoided as much as possible IMO. For example, I do not want my students to take it as guaranteed that `sizeof int` produces `4`, because on Arduino Uno, an `int` is a 2-byte value.

Currently, it is mainly for educational uses for a MOOC course I am running (and fun).

## Prerequisites

* NodeJS or
* A modern browser

## How to use

Installation

```
npm install JSCPP
```

or (to use lastest cutting-edge version or to contribute)

```
git clone https://github.com/felixhao28/JSCPP.git
cd JSCPP
npm install .
```

### With NodeJS

Use __launcher.run__

```js
var JSCPP = require("JSCPP");
var launcher = JSCPP.launcher;
var code =    "#include <iostream>"    + "\n"
            + "using namespace std;"   + "\n"
            + "int main() {"           + "\n"
            + "    int a;"             + "\n"
            + "    cin >> a;"          + "\n"
            + "    cout << a << endl;" + "\n"
            + "    return 0;"          + "\n"
            + "}"                      + "\n"
;
var input = "4321";
var exitcode = launcher.run(code, input);
console.info("program exited with code " + exitcode);
```

See _demo/example.coffee_ for example.

Or do it step by step:

Configuring standard IO and libraries
```js
var JSCPP = require("JSCPP");
var Runtime = JSCPP.Runtime;
var inputbuffer = "1 2 3";
var rt = new Runtime({
	stdio: {
		drain: function() {
			// This method will be called when program requires additional input
			// so you can return "1", "2" and "3" seperately during three calls.
			// Returning null value means EOF.
			var x = inputbuffer;
			inputbuffer = null;
			return x;
		},
		write: function(s) {
			process.stdout.write(s);
		}
	},
	includes: {
		iostream: require("./includes/iostream"),
		cmath: require("./includes/cmath")
		// Of course you can add more libraries here.
		// These libraries are only made available for "include" to happen
		// and NOT ready to be used in your cpp code.
		// You should use proper include directive to include them
		// or call load method on them directly (shown below).
	}
});
```

Using preprocessor (experimental)
```js
var preprocessor = JSCPP.preprocessor;
console.log("preprocessing starting");
code = preprocessor(rt, prepast, code);
console.log("preprocessing finished");
```

(Optional) If you choose not to use preprocessor, directives like `#include <...>` will not work, you need to load libraries manually
```js
rt.config.includes.iostream.load(rt);
rt.config.includes.cmath.load(rt);
```

Building AST
```js
var ast = JSCPP.ast;
var tree = ast.parse(code);
console.log("passed syntax check");
```

Interpreting AST (from global main function)
```js
var Interpreter = JSCPP.Interpreter;
var interpreter = new Interpreter(rt);
interpreter.run(tree);
var exitCode = rt.getFunc("global", "main", [])(rt, null, []).v;
console.info("program exited with code " + exitCode);
```

A full example is available in *demo/verbose_example.coffee*.

Use __debugger__

Unlike most other IDE, the debugging here is actually a replay of the execution.

```js
var mydebugger = new JSCPP.Debugger();
var exitCode = JSCPP.launcher.run(code, input, {debug: true, debugger: mydebugger});
// continue to the next statement
var hasNext = mydebugger.next();
if (!hasNext) {
	console.log("program exited with code " + exitCode);
}
// go back to the previous statement
var hasPrev = mydebugger.prev();
// examine the content of the output window
var outputContent = mydebugger.output();
// the content of the statement to be executed next
{'fraction_non_alphanumeric': 0.11549362305148796, 'fraction_numerical': 0.00401511572980633, 'mean_word_length': 3.381272633212623, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1807888', 'n_tokens_mistral': 2662, 'n_tokens_neox': 2487, 'n_words': 1039}