#jslike JavaScript-like "var" (Number/String/Array/Object/function) for C++
jslike let's you create objects, assign properties, use arrays and strings a JavaScript way right in your C++ code by exposing the single var class.
###Currently implemented
- Number, String, Array, Object, Boolean.
- Pass by value for Numbers/Boolean, pass by reference for Array/Object.
####Functions and properties:
var = var, int, double, char*, wchar_t*, bool-- construct var from basic typesvar.toString()var[#]-- Array index accessvar[key]-- Object property accessvar[#]-- String character accessvar + var-- Arithmetic/logic operators++--+-/*%&|&&||==!=<>var + var-- String concatenation, comparison<>==var.round()var.charAt()var.charCodeAt()var.toNumber()var::fromCharCode()-- static functionvar.split()var.objectKeys()-- JavaScript'sObject.keys()var.indexOf()-- Array/Stringvar.push()var.pop()var.Push()-- JavaScriptunshift()(shift is a reserved word in C++).var.Pop()-- JavaScriptshift()var.length()var.splice()var.slice()var.join()var.typeOf()var.del()-- delete key/value pairs from Objectvar.has()-- check if key is set (exists) in the Object.undefined-- set and compare vars withundefinedor Undefined().JSON.stringify()JSON.parse()
Conversion to basic C++ types:
wchar_t* getStringPointer()char* getStringAllocUtf()char* getStringAllocAscii()int toDouble()int toInt()
Experimental complex literals:
var::arr() = a,b,c,d,....var::obj() = a,b,c,d,....ARR(1,2,3,4)OBJ("a", 2, "b", 4)log(...)-- function to conveniently output to console
###Not yet implemented
- mark&sweep GC
- functions, lambdas, closures
- map, sort, filter etc...
##Examples
- Minimal program
- Undefined variables and numbers
- Strings
- Mix numbers and strings
- Arrays
- log()
- Array.slice()
- Array splice()
- Array indexOf() and String indexOf()
- Array literal notation
- concatAll()
- Objects
- Converting between var and basic types
- Getting a pointer to a character buffer of a String.
- Passing var as an argument
The library is included by source, so you simply add these two lines:
#include "jslike.h"usingnamespacejslike;jslike tries not to pollute your namespace as much as possible, so everything is inside the "namespace jslike".
###Minimal program
// hello.cpp
#include"stdio.h"
#include"jslike.h"usingnamespacejslike;intmain() {
var hello = "hello world привет мир 你好世界";
log(hello)
}output:
hello world привет мир 你好世界###Undefined variables, number variables
varx;vary=42;log(x,x.typeOf());log(y,y.typeOf());x=3,y=4;log(x+y);log(x-4,x+5,x/y,x*y);output:
undefined undefined42 number7-1 8 0.75 12###Strings
varhello="hello";varworld;world="world";log(hello+"-"+world+"!");// string concatenationlog(hello,world);// log can accept unlimited number or argumentslog(hello.indexOf("ll"));output:
hello-world!hello world2vars="Nuke the entire site from orbit";log("Sentence length:",s.length());log(s.slice(0,4),s.slice(-10));for(inti=0;i<4;i++)log(s.charAt(i),s.charCodeAt(i));output:
Sentence length: 31Nuke from orbitN 78u 117k 107e 101###Mix numbers and strings
vara="A",b=1;// 'string + number' implies conversion to stringlog(a+b);log((var)"Received #"+12+" from "+2+" planets");log((var)"2 + 2 = "+(2+2));// explicit var constructoroutput:
A1Received #12 from 2 planets2 + 2 = 4###Arrays
Declare empty array and push something into it.
varA=Array;A.push("planet");A.push("LV");A.push(426);log(A);Array toString() is called before output.
output:
planet, LV, 426log() is console.log() of JavaScript.
log can print any var or anything that a var constructor accepts.
vara=1;varb="hello";varc=Array;c.push(100);c.push(200);log(a,b,c,500,"world");output:
1 hello 100, 200 500 world###Array.slice()
varfruits;fruits=(Arr"Banana","Orange","Lemon","Apple","Mango");varcitrus=fruits.slice(1,3);log(citrus);The contents of citrus will be:
Orange, Lemon###Array splice()
Unlike JavaScript you cannot insert more than one item in splice().
varfruits=(Arr"Banana","Orange","Apple","Mango");fruits.splice(2,0,"Kiwi");fruits.splice(2,0,"Lemon");log(fruits);output:
Banana, Orange, Lemon, Kiwi, Apple, Mango ###Array indexOf() and String indexOf()
varq;q=(Arr0,1,2,3,4,5,6);varj=q.indexOf(3);log(q);log(j);vara="hello world";log(a.indexOf("wo"));output:
0, 1, 2, 3, 4, 5, 6 3 6 ###Array literal notation
The closest syntax we could achieve in C++ to cozy JavaScript Array literal notation is this: var x = (Arr list-of-items).
This syntax is achieved with overloading operator= and operator, for a temporary class arrset. And then hiding it under the macro Arr.
Arr is a #define macro that expands to var::arr() =.
varplanets=(Arr"Earth","Venus","Mars","Jupiter");varstars=(Arr"Vega","Aldebaran","Altair","Decrux");for(vari=0;i<planets.length();i++)log((var)"Planet #"+(i+1),planets[i]);log("Stars:",stars);log("Space objects:",planets.concat(stars));output:
Planet #1 Earth Planet #2 Venus Planet #3 Mars Planet #4 Jupiter Stars: Vega, Aldebaran, Altair, Decrux Space objects: Earth, Venus, Mars, Jupiter, Vega, Aldebaran, Altair, Decrux ###concatAll()
Unfortunately there is no way use varargs/stdargs with class constructors, so we cannot haveconcat(a,...) syntax. Instead var.concatAll() is provided.
vara=Array;a.push((Arr1,2,3));a.push((Arr4,5,6));a.push((Arr7,8,9));log(JSON.stringify(a));varb=a.concatAll();log(JSON.stringify(b));output:
[[1,2,3],[4,5,6],[7,8,9]] [1,2,3,4,5,6,7,8,9] ###Objects
varxy=Object;// Declare empty objectxy["x"]=100;xy["y"]=200;log(JSON.stringify(xy));log(xy["z"]);output:
{x:100,y:200} undefined Object literal notation:
varo=(Obj"x",100,"y",400);log(JSON.stringify(o));output:
{x:100,y:400} Property access. Unfortunately there is no way to enable "o.x" style notation in C++. So we have to use var[key] syntax.
o["x"]++;o["y"]=o["x"]*2;log(JSON.stringify(o));output:
{x:101,y:202} Delete existing propery specified by the key name:
if(o.has("x"))o.del("x");log(JSON.stringify(o));output:
{ y: 202 }###Converting between var and basic types
vara=123.456;inti=a.toInt();doubled=a.toDouble();printf("Basic types, integer=%i, double=%f\n",i,d);output:
Basic types, integer=123, double=123.456000###Getting a pointer to a character buffer of a String.
Internally strings are stored as UTF16/32 AKA wchar_t.
You can either get a pointer to a internal wchar_t* buffer, or get a pointer to a char* copy of that buffer, allocated and copied for you in either ascii or utf8.
wchar_t* var::getStringPointer() returns a pointer to an internal data, it
is valid until the var exists. Do not delete the pointer returned from this function.
When function name has Alloc() in it, it means you are responsible for the deallocation of the returned data. Use C++ delete operator when you are done.
var var::getStringAllocUtf() and var var::getStringAllocUtf() alloc and copy the contents.
varhello="world,мир,世界";char*str=hello.getStringAllocUtf();printf("char* = %s\n",str);deletestr;str=hello.getStringAllocAscii();printf("char* = %s\n",str);deletestr;wchar_t*w=hello.getStringPointer();for(inti=0;i<hello.length().toInt();i++){printf("%i: char code: %i\n",i,(int)w[i]);}output:
char* = world,мир,世界char* = world,<8@,�L0: char code: 1191: char code: 1112: char code: 1143: char code: 1084: char code: 1005: char code: 446: char code: 10847: char code: 10808: char code: 10889: char code: 4410: char code: 1999011: char code: 30028###Passing var as an argument
Arrays and Objects are passed by reference, just like in JavaScript. Strings, Numbers, Booleans are passed by value. This example illustrates this principle:
#include "stdio.h"
#include "jslike.h"usingnamespacejslike;varsum10(vara,varb){a=a*10;b=b*10;returna+b;}voidpopAndPrint(vara){log(a.pop());}intmain(){varx=400,y=500;log(sum10(x,y));log(x,y);varb;b=(Arr100,200,300);popAndPrint(b);popAndPrint(b);log("What remains in b:",b);}output:
9000 400 500 300 200 What remains in b: 100 ##Implementation details.
###Operator overloading
jslike intensively relies on C++ operator overloading. var is declared as struct var, hence all members are public.
The code is C++98 compatible. No modern C++2015 features are used.
###Amalgamated header jslike is header-only library, there is no object file involved. You just include it in your source and it includes other files. The complete size of all files together is about 1700 LOC at the moment of this writing.
jslike.h includes few more headers, but for your convenience _jslike.h is also provided, which is an amalgamation or basically concatenation of all headers into one single file. You can just grab it and copy to your project directory if you need.