├── .gitignore ├── README.md ├── inc ├── SmartVar.h └── linker.ld ├── package.json ├── server.js ├── server.sh ├── src ├── compile.js ├── infer.js ├── math.js └── utils.js ├── test.js ├── test_espruino.js ├── tests └── test.js └── tmp └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | .project 4 | .settings 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Espruino Compiler 2 | =============== 3 | 4 | See [the Espruino Compilation Page](http://www.espruino.com/Compilation) 5 | 6 | This project does the following: 7 | 8 | * Turns JavaScript code into C++ (that calls into Espruino library functions for more complicated operations) 9 | * Compiles the code with GCC 10 | * Links and Extracts a relocatable blob of Thumb code 11 | * Formats it into JS that can be run in [Espruino](http://www.espruino.com) 12 | 13 | Files 14 | ----- 15 | 16 | * `src/utils.js` - general utilities 17 | * `src/infer.js` - Type inferral on parse tree 18 | * `src/compile.js` - Parse tree -> C++, and calling of GCC 19 | * `server.js` - server that performs compilation for the Web IDE 20 | * `test.js` - simple command-line test 21 | * `test_espruino.js` - test in such a way that the C code is compiled into Espruino - allowing nice easy GDB debug 22 | 23 | 24 | Setup 25 | ----- 26 | 27 | You need: 28 | 29 | * A new node.js 30 | * [gcc-arm-embedded](https://launchpad.net/gcc-arm-embedded/+download) in your path 31 | 32 | Running 33 | ------- 34 | 35 | * Run `node server.js` 36 | * Go into Web IDE settings and set `Communications / JavaScript Compiler URL` to `http://localhost:32766` 37 | -------------------------------------------------------------------------------- /inc/SmartVar.h: -------------------------------------------------------------------------------- 1 | typedef char int8_t; 2 | typedef short int16_t; 3 | typedef int int32_t; 4 | 5 | /* very dodgy reference holding implementation, that allows 6 | us to pass most of the locking/unlocking to GCC. 7 | 8 | Mostly this gets collapsed down to virtually nothing, but 9 | assignments create a jsvLockAgainSafe. */ 10 | class SV { 11 | JsVar *v; 12 | bool owned; 13 | public: 14 | inline __attribute__((always_inline)) SV( const SV& o ) { 15 | owned = true; 16 | v = jsvLockAgainSafe(o.v); 17 | } 18 | inline __attribute__((always_inline)) SV &operator=(const SV &o) { 19 | if (owned) jsvUnLock(v); 20 | owned = true; 21 | v = jsvLockAgainSafe(o.v); 22 | return *this; 23 | } 24 | inline __attribute__((always_inline)) SV(JsVar *value) { 25 | owned = true; 26 | v=value; 27 | } 28 | inline __attribute__((always_inline)) SV() { 29 | owned = false; 30 | v=0; 31 | } 32 | inline __attribute__((always_inline)) ~SV() { 33 | if (owned) jsvUnLock(v); 34 | } 35 | inline __attribute__((always_inline)) operator JsVar*() const { return v; } 36 | static inline __attribute__((always_inline)) SV notOwned(JsVar *value) { 37 | SV s = SV(value); 38 | s.owned = false; 39 | return s; 40 | } 41 | inline __attribute__((always_inline)) JsVar *give() { 42 | if (!owned) v = jsvLockAgainSafe(v); 43 | owned = false; 44 | return v; 45 | } 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /inc/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(entryPoint) 2 | 3 | MEMORY 4 | { 5 | RAM (xrw) : ORIGIN = 0, LENGTH = 100K 6 | } 7 | 8 | SECTIONS 9 | { 10 | .entrypoint : 11 | { 12 | . = ALIGN(4); 13 | *(.entryPoint) 14 | } 15 | /* We put everything in .text section as we load everything into RAM as one binary string */ 16 | 17 | .text : 18 | { 19 | . = ALIGN(4); 20 | *(.text) 21 | *(.text*) 22 | *(.rodata) 23 | *(.rodata*) 24 | . = ALIGN(4); 25 | *(.data) /* .data sections */ 26 | *(.data*) /* .data* sections */ 27 | . = ALIGN(4); 28 | *(.bss) 29 | *(.bss*) 30 | *(COMMON) 31 | . = ALIGN(4); 32 | } >RAM 33 | 34 | /* Remove stuff we don't want */ 35 | /DISCARD/ : 36 | { 37 | libc.a ( * ) 38 | libm.a ( * ) 39 | libgcc.a ( * ) 40 | *(.ARM.*) 41 | *(.comment) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "acorn": "^1.2.2" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | // Simple webserver that takes requests for compilation and sends back the result 2 | var acorn = require("acorn"); 3 | var qs = require('querystring'); 4 | var utils = require("./src/utils.js"); 5 | compileFunction = require("./src/compile.js").compileFunction; 6 | compileCFunction = require("./src/compile.js").compileCFunction; 7 | 8 | function compile_js(js, options, callback) { 9 | var ast = acorn.parse(js, { ecmaVersion : 6 }); 10 | console.log(ast); 11 | var node = ast.body[0]; 12 | if (node.type=="FunctionDeclaration" && 13 | node.body.type=="BlockStatement" && 14 | node.body.body.length>0 && 15 | node.body.body[0].type=="ExpressionStatement" && 16 | node.body.body[0].expression.type=="Literal" && 17 | node.body.body[0].expression.value=="compiled") { 18 | compileFunction(node, options, callback); 19 | } else { 20 | throw new Error("Not Valid code"); 21 | } 22 | } 23 | 24 | function respondWithCompilerMessage(response, message, code) { 25 | response.end((code?(code.trim()+"\n"):"")+"console.log("+JSON.stringify( 26 | "[ COMPILER MESSAGE ] : "+message)+")"); 27 | } 28 | 29 | function handlePost(post, response) { 30 | console.log("POST ",post); 31 | response.setHeader("Access-Control-Allow-Origin", "*"); 32 | 33 | var boardInfo; 34 | if (post.board) 35 | boardInfo = utils.SUPPORTED_BOARDS[post.board]; 36 | if (boardInfo===undefined) 37 | return respondWithCompilerMessage(response, "Only official Espruino boards are supported by the Compiler Service", post.js); 38 | 39 | var exports; 40 | if (post.exptr) { 41 | exports = parseInt(post.exptr); 42 | } else { 43 | try { 44 | exports = JSON.parse(post.exports); 45 | } catch (ex) { 46 | respondWithCompilerMessage(response, "Unable to parse EXPORTS", post.js); 47 | return; 48 | } 49 | } 50 | 51 | var options = { 52 | exports : exports, 53 | board : post.board, 54 | boardInfo : boardInfo 55 | }; 56 | 57 | if (post.js) { 58 | try { 59 | compile_js(post.js, options, function(err, code) { 60 | if (err) return respondWithCompilerMessage(response,err, post.js); 61 | console.log("----------------------------------------"); 62 | console.log(code); 63 | console.log("----------------------------------------"); 64 | response.end(code); 65 | }); 66 | } catch (ex) { 67 | console.log("==============================================="); 68 | console.log(post.js); 69 | console.log("----------------------------------------"); 70 | if ("object"==typeof ex && ex.stack)console.log(ex.stack); 71 | else console.log(ex.toString()); 72 | console.log("==============================================="); 73 | respondWithCompilerMessage(response, ex.toString(), post.js); 74 | } 75 | } else if (post.c) { 76 | try { 77 | compileCFunction(post.c, options, function(err, code) { 78 | if (err) return respondWithCompilerMessage(response,err, post.js); 79 | console.log("----------------------------------------"); 80 | console.log(code); 81 | console.log("----------------------------------------"); 82 | response.end(code); 83 | }); 84 | } catch (ex) { 85 | console.log("==============================================="); 86 | console.log(post.c); 87 | console.log("----------------------------------------"); 88 | if ("object"==typeof ex && ex.stack)console.log(ex.stack); 89 | else console.log(ex.toString()); 90 | console.log("==============================================="); 91 | respondWithCompilerMessage(response, ex.toString(), post.js); 92 | } 93 | } else { 94 | respondWithCompilerMessage(response, "Unknown compilation arguments", post.js); 95 | } 96 | } 97 | 98 | var server = require("http").createServer(function (request, response) { 99 | if (request.method=="POST") { 100 | var body = ''; 101 | request.on('data', function (data) { 102 | body += data; 103 | 104 | // Too much POST data, kill the connection! 105 | if (body.length > 1e6) 106 | request.connection.destroy(); 107 | }); 108 | request.on('end', function () { 109 | var post = qs.parse(body); 110 | handlePost(post, response); 111 | }); 112 | 113 | 114 | } else { 115 | response.end("Espruino compilation server"); 116 | } 117 | }); 118 | 119 | server.listen(32766, function() { 120 | address = server.address(); 121 | console.log("Opened server on %j", address); 122 | }); 123 | -------------------------------------------------------------------------------- /server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $EUID -eq 0 ]]; then 4 | echo "Root user not allowed!" 2>&1 5 | exit 1 6 | fi 7 | 8 | cd `dirname $0` 9 | 10 | RUNNING=1 11 | while [ $RUNNING ]; do 12 | rm -f *.elf *.cpp 13 | node server.js 14 | echo ------------------------------------------- 15 | echo Server stopped - restarting... 16 | echo ------------------------------------------- 17 | sleep 2s 18 | done 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/compile.js: -------------------------------------------------------------------------------- 1 | var utils = require("./utils.js"); 2 | var infer = require("./infer.js").infer; 3 | var acorn_walk = require("acorn/dist/walk"); 4 | 5 | var locals; 6 | var cCodeIndent = 0; 7 | var cCode = ""; 8 | var cTempVar = 0; 9 | 10 | function getType(node) { 11 | if (!node.varType) return "JsVar"; 12 | return node.varType; 13 | } 14 | 15 | function getCType(t) { 16 | if (t=="JsVar") return "SV"; 17 | return t; 18 | } 19 | 20 | function getField(object, field, computed, wantName) { 21 | if (field.type=="Identifier" && !computed) { 22 | return callSV("jspGetNamedField", object, JSON.stringify(field.name), wantName ? 1 : 0); 23 | } else { 24 | return callSV("jspGetVarNamedField", object, handleAsJsVarSkipName(field), wantName ? 1 : 0); 25 | } 26 | } 27 | 28 | function isLocal(name) { 29 | return name in locals; 30 | } 31 | 32 | function isNodeZero(node) { 33 | return node.type=="Literal" && node.value==0; 34 | } 35 | 36 | var nodeHandlers = { 37 | 38 | "Literal" : function(node) { 39 | if (getType(node)=="int" && utils.isInt(node.value)) 40 | return node.value; 41 | if (getType(node)=="bool" && utils.isBool(node.value)) 42 | return node.value; 43 | 44 | if (typeof node.value == "string") 45 | return callSV("jsvNewFromString", JSON.stringify(node.value)); 46 | else if (utils.isBool(node.value)) 47 | return callSV("jsvNewFromBool", node.value); 48 | else if (utils.isFloat(node.value)) 49 | return callSV("jsvNewFromFloat", node.value); 50 | else if (utils.isInt(node.value)) 51 | return callSV("jsvNewFromInteger", node.value); 52 | else throw new Error("Unknown literal type "+typeof node.value); 53 | }, 54 | "Identifier" : function(node) { 55 | if (isLocal(node.name)) { 56 | if (getType(node)=="JsVar" && !locals[node.name].isSV) 57 | return "SV::notOwned("+node.name+")"; 58 | return node.name; 59 | } 60 | return callSV("jspGetNamedVariable", JSON.stringify(node.name)); 61 | }, 62 | 63 | "VariableDeclaration" : function (node) { 64 | var c = ""; 65 | node.declarations.forEach(function (node) { 66 | var typ = locals[node.id.name].type; 67 | c += getCType(typ)+" "+node.id.name+(node.init?(" = "+handleAsType(node.init, typ)):"")+";\n"; 68 | }); 69 | return c; 70 | }, 71 | 72 | "MemberExpression" : function(node) { 73 | var obj = handleAsJsVarSkipName(node.object); 74 | return getField(obj, node.property, node.computed, true); 75 | }, 76 | "UnaryExpression" : function(node) { 77 | if (node.operator=="!") { 78 | return "!"+handleAsBool(node.argument); 79 | } else if (node.operator=="~") { 80 | return "~"+handleAsInt(node.argument); 81 | } else if (node.operator=="-" || node.operator=="+") { 82 | var expr = { 83 | type : "BinaryExpression", 84 | operator : node.operator, 85 | left : { type : "Literal", value : 0, varType : "int" }, 86 | right : node.argument, 87 | varType : node.argument.varType 88 | }; 89 | return handle(expr, node.argument.varType); 90 | } else { 91 | throw new Error("Only '!', '~', '-', and '+' are implemented as a unary expression"); 92 | } 93 | }, 94 | "BinaryExpression" : function(node) { 95 | // These 2 nodes have no effect with one argument as 0 - optimise 96 | if (["|","^"].indexOf(node.operator)>=0) { 97 | if (isNodeZero(node.left)) return handleAsInt(node.right); 98 | if (isNodeZero(node.right)) return handleAsInt(node.left); 99 | } 100 | // otherwise do the full expr 101 | if ((getType(node)=="int" || getType(node)=="bool") && 102 | (getType(node.left)=="int" || getType(node.left)=="bool") && 103 | (getType(node.right)=="int" || getType(node.right)=="bool")) { 104 | return "(" + handleAsInt(node.left) + " " + node.operator + " " + handleAsInt(node.right) + ")"; 105 | } else { 106 | return convertJsVarToType( 107 | callSV("jsvMathsOp",handleAsJsVarSkipName(node.left),handleAsJsVarSkipName(node.right),utils.getMathsOpOperator(node.operator)), 108 | getType(node)); 109 | } 110 | }, 111 | "LogicalExpression" : function(node) { 112 | if (getType(node)=="bool") { 113 | return "(" + handleAsBool(node.left) + " " + node.operator + " " + handleAsBool(node.right) + ")"; 114 | } else 115 | throw new Error("Unhandled non-boolean LogicalExpression "+node.operator); 116 | }, 117 | "CallExpression" : function(node) { 118 | if (node.varType="int" && 119 | node.callee.type == "Identifier" && 120 | ["peek8","peek16","peek32"].indexOf(node.callee.name)>=0 && 121 | node.arguments.length==1) { 122 | var type = "int"+node.callee.name.substr(4)+"_t"; 123 | return "(*(volatile "+type+"*)(void*)"+handleAsInt(node.arguments[0])+")"; 124 | } 125 | if (node.varType="int" && 126 | node.callee.type == "Identifier" && 127 | ["poke8","poke16","poke32"].indexOf(node.callee.name)>=0 && 128 | node.arguments.length==2 && 129 | ["int","bool"].indexOf(getType(node.arguments[1]))>=0) { 130 | var type = "int"+node.callee.name.substr(4)+"_t"; 131 | return "((*(volatile "+type+"*)(void*)"+handleAsInt(node.arguments[0])+") = ("+handleAsInt(node.arguments[1])+"))"; 132 | } 133 | 134 | // TODO: check for simple peek and poke, and implement them directly 135 | var initCode = ""; 136 | var args = node.arguments.map(function(node) { 137 | var tv = getTempVar(); 138 | initCode += "SV "+tv+"="+handleAsJsVarSkipName(node)+";"; 139 | return tv; 140 | }); 141 | 142 | // slightly odd arrangement needed to ensure vars don't unlock until later 143 | initCode += "JsVar *args["+node.arguments.length+"] = {"+args.join(", ")+"};"; 144 | // luckily GCC lets us package a block inside an expression `({...})` 145 | // otherwise we'd have to do some really strange stuff 146 | 147 | if (node.callee.object != undefined /*&& callee.type == "MemberExpression"*/) { 148 | var thisVar = getTempVar(); 149 | initCode += "SV "+thisVar+"="+handleAsJsVarSkipName(node.callee.object)+";"; 150 | var methodVar = getField(thisVar, node.callee.property, node.computed, false); 151 | 152 | return "({"+initCode+ 153 | callSV("jspeFunctionCall",methodVar, 0/*funcName*/, thisVar/*this*/, 0/*isParsing*/, node.arguments.length/*argCount*/, "args"/* argPtr */)+";})"; 154 | } else { 155 | // Simple function call (not method) 156 | return "({"+initCode+ 157 | callSV("jspeFunctionCall",handleAsJsVarSkipName(node.callee), 0/*funcName*/, 0/*this*/, 0/*isParsing*/, node.arguments.length/*argCount*/, "args"/* argPtr */)+";})"; 158 | } 159 | }, 160 | 161 | "ConditionalExpression" : function(node) { 162 | var t = getType(node); 163 | return "("+handleAsBool(node.test)+"?"+handleAsType(node.consequent,t)+":"+handleAsType(node.alternate,t)+")"; 164 | }, 165 | "AssignmentExpression" : function(node, needsResult) { 166 | if (getType(node.left)=="JsVar") { 167 | var rhs; 168 | if (node.operator=="=") { 169 | rhs = handleAsJsVar(node.right); 170 | } else { 171 | var op, postinc = false; 172 | if (node.operator == "+=") op = "+"; 173 | if (node.operator == "-=") op = "-"; 174 | if (node.operator == "*=") op = "*"; 175 | if (node.operator == "/=") op = "/"; 176 | if (node.operator == "%=") op = "%"; 177 | if (node.operator == "&=") op = "&"; 178 | if (node.operator == "^=") op = "^"; 179 | if (node.operator == "|=") op = "|"; 180 | if (op===undefined) throw new Error("Unhandled AssignmentExpression "+node.operator); 181 | var expr = { 182 | type : "BinaryExpression", 183 | operator : op, 184 | left : node.left, 185 | right : node.right, 186 | }; 187 | rhs = handleAsJsVar(expr); 188 | } 189 | if (node.left.type=="Identifier" && isLocal(node.left.name)) 190 | return handleAsJsVar(node.left) +" = "+ rhs; 191 | else { 192 | // replaceWith doesn't return anything, so we must store the value ourselves 193 | if (needsResult) { 194 | var tv = getTempVar(); 195 | return "({SV "+tv+"="+handleAsJsVar(node.left)+";"+call("jsvReplaceWith", tv, rhs)+";"+tv+";})"; 196 | } else 197 | return call("jsvReplaceWith", handleAsJsVar(node.left), rhs); 198 | } 199 | } else { 200 | return handle(node.left, true) + " "+ node.operator + " " + handle(node.right, true); 201 | } 202 | }, 203 | "UpdateExpression" : function(node, needsResult) { 204 | var op = { 205 | "++" : "+=", 206 | "--" : "-=" 207 | }[node.operator]; 208 | if (op===undefined) throw new Error("Unhandled UpdateExpression "+node.operator); 209 | var expr = { 210 | type : "AssignmentExpression", 211 | operator : op, 212 | left : node.argument, 213 | right : { 214 | type : "Literal", 215 | value : 1, 216 | varType : node.argument.varType 217 | }, 218 | varType : node.argument.varType 219 | }; 220 | if (node.prefix || !needsResult) { 221 | // all great - we just treat it like += 1 222 | return handle(expr, needsResult); 223 | } else { 224 | // it's postfix - we must store the value first, and return that 225 | // this isn't great - as we search for the variable by name twice 226 | var tv = getTempVar(); 227 | return "({SV "+tv+"="+handleAsJsVarSkipName(node.argument)+";"+handle(expr, true)+";"+tv+";})"; 228 | } 229 | }, 230 | "EmptyStatement" : function(node) { 231 | }, 232 | "ExpressionStatement" : function(node) { 233 | out(handle(node.expression, false/* no result needed */)+";\n"); 234 | }, 235 | "BlockStatement" : function(node) { 236 | node.body.forEach(function(s) { 237 | out(handle(s, false/* no result needed */)); 238 | }); 239 | }, 240 | "ReturnStatement" : function(node) { 241 | out("return "+handleAsJsVar(node.argument)+".give();\n"); 242 | }, 243 | "IfStatement" : function(node) { 244 | out("if ("+handleAsBool(node.test)+") {\n"); 245 | setIndent(1); 246 | out(handle(node.consequent, false/* no result needed */)); 247 | if (!node.alternate) { 248 | setIndent(-1); 249 | out("}\n"); 250 | } else { 251 | setIndent(-1); 252 | out("} else {\n"); 253 | setIndent(1); 254 | out(handle(node.alternate, false/* no result needed */)); 255 | setIndent(-1); 256 | out("}\n"); 257 | } 258 | }, 259 | "ForStatement" : function(node) { 260 | var initCode = handle(node.init, false/* no result needed */).trim(); 261 | if (initCode.substr(-1)!=";") initCode += ";"; 262 | out("for ("+initCode+""+handleAsBool(node.test)+";"+handle(node.update, false/* no result needed */)+") {\n"); 263 | setIndent(1); 264 | out(handle(node.body, false/* no result needed */)); 265 | setIndent(-1); 266 | out("}\n"); 267 | }, 268 | "WhileStatement" : function(node) { 269 | out("while ("+handleAsBool(node.test)+") {\n"); 270 | setIndent(1); 271 | out(handle(node.body, false/* no result needed */)); 272 | setIndent(-1); 273 | out("}\n"); 274 | }, 275 | }; 276 | 277 | function handle(node, needsResult) { 278 | if (node.type in nodeHandlers) 279 | return nodeHandlers[node.type](node, needsResult); 280 | console.warn("Unknown", node); 281 | throw new Error(node.type+" is not implemented yet"); 282 | } 283 | 284 | function convertJsVarToType(v, type) { 285 | if (type=="int") return call("jsvGetInteger", v); 286 | if (type=="bool") return call("jsvGetBool", v); 287 | if (type=="JsVar") return v; 288 | throw new Error("convertJsVarToType unhandled type "+JSON.stringify(type)); 289 | } 290 | 291 | function handleAsJsVar(node) { 292 | if (getType(node)=="int") return callSV("jsvNewFromInteger", handle(node, true)); 293 | if (getType(node)=="bool") return callSV("jsvNewFromBool", handle(node, true)); 294 | return handle(node, true); 295 | } 296 | 297 | function handleAsJsVarSkipName(node) { 298 | if (node.isNotAName) return handleAsJsVar(node); 299 | return callSV("jsvSkipName", handleAsJsVar(node)); 300 | } 301 | 302 | function handleAsInt(node) { 303 | if (getType(node)=="int" || getType(node)=="bool") return handle(node, true); 304 | return call("jsvGetInteger", handleAsJsVarSkipName(node)); 305 | } 306 | 307 | function handleAsBool(node) { 308 | if (getType(node)=="bool") return handle(node, true); 309 | if (getType(node)=="int") return "(("+handle(node, true)+")!=0)"; 310 | return call("jsvGetBool", handleAsJsVarSkipName(node)); 311 | } 312 | 313 | function handleAsType(node, type) { 314 | if (type=="bool") return handleAsBool(node); 315 | if (type=="int") return handleAsInt(node); 316 | if (type=="JsVar") return handleAsJsVarSkipName(node); 317 | throw new Error("handleAsType unhandled type "+JSON.stringify(type)); 318 | } 319 | 320 | 321 | 322 | function getTempVar() { 323 | return "_v"+cTempVar++; 324 | } 325 | 326 | function getIndent() { 327 | return " ".substr(0,cCodeIndent); 328 | } 329 | 330 | function setIndent(i) { 331 | cCodeIndent+=i; 332 | var n = cCode.length-1; 333 | while (cCode[n]===" ") n--; 334 | while (cCode[n]==="\n") n--; 335 | cCode = cCode.substr(0,n+1)+"\n"+getIndent(); 336 | } 337 | 338 | function out(txt) { 339 | if (txt===undefined) return; 340 | cCode += txt.replace("\n","\n"+getIndent()); 341 | } 342 | 343 | function call(funcName) { 344 | var c = funcName+"("; 345 | var args = Array.prototype.slice.call(arguments, 1); 346 | c += args.join(", "); 347 | c += ")"; 348 | return c; 349 | } 350 | 351 | function callSV(funcName) { 352 | return "SV("+call.apply(this,arguments)+")"; 353 | } 354 | 355 | exports.jsToC = function(node) { 356 | // Initialise 357 | locals = []; 358 | cCode = ""; 359 | cCodeIndent = 0; 360 | cTempVar = 0; 361 | // Infer types 362 | infer(node); 363 | // Look at parameters 364 | var paramSpecs = []; 365 | var params = node.params.map(function( node ) { 366 | node.isNotAName = true; 367 | paramSpecs.push(getType(node)); 368 | locals[node.name] = { 369 | type : getType(node), 370 | isSV: false 371 | }; 372 | return "JsVar *"+node.name; 373 | }); 374 | // Look at locals 375 | var localWalker = { 376 | "VariableDeclaration" : function (node) { 377 | node.declarations.forEach(function (node) { 378 | locals[node.id.name] = { 379 | type : getType(node.id), 380 | isSV: getType(node.id)=="JsVar", // not an SV if it's not a JsVar 381 | }; 382 | // walked doesn't handle VariableDeclarator.init 383 | if (node.init) acorn_walk.simple(node.init, localWalker); 384 | }); 385 | }, 386 | "Identifier" : function(node) { 387 | if (isLocal(node.name)) { 388 | node.isNotAName = true; 389 | } 390 | } 391 | }; 392 | acorn_walk.simple(node, localWalker); 393 | console.log("Locals: ",locals); 394 | 395 | // Get header stuff 396 | cCode += require("fs").readFileSync("inc/SmartVar.h").toString(); 397 | // Now output 398 | out('extern "C" {\n'); 399 | setIndent(1); 400 | var functionName = "entryPoint"; 401 | var cArgSpec = "__attribute__ ((section (\".entrypoint\"))) JsVar *"+functionName+"("+params.join(", ")+")"; 402 | out(cArgSpec + " {\n"); 403 | setIndent(1); 404 | // Serialise all statements 405 | node.body.body.forEach(function(s, idx) { 406 | if (idx==0) return; // we know this is the 'compiled' string 407 | out(handle(s, false/* no result needed*/)); 408 | }); 409 | out("return 0; // just in case\n"); 410 | setIndent(-1); 411 | out("}\n"); 412 | setIndent(-1); 413 | out("}\n"); 414 | //out("int main() { foobar(_cnt++); return 0; }\n"); 415 | 416 | return { 417 | code : cCode, 418 | functionName : functionName, 419 | cArgSpec : cArgSpec, 420 | jsArgSpec : "JsVar("+paramSpecs.join(",")+")" 421 | }; 422 | }; 423 | 424 | function gcc(code, options, callback) { 425 | var crypto = require('crypto'); 426 | var filename = "tmp/out"+crypto.randomBytes(4).readUInt32LE(0); 427 | 428 | code = code.replace(/^\s*#include\s*<([^>]+)>\s*/gm, (m, file) => { 429 | if (file == 'math.h') 430 | return (require('./math.js')[options.boardInfo.cpu] || ''); 431 | return m; 432 | }); 433 | 434 | // save to file 435 | require("fs").writeFileSync(filename+".cpp", code); 436 | // now run gcc 437 | var exec = require('child_process').exec; 438 | /*child = exec("gcc "+filename+".cpp -fno-exceptions -m32 -o "+filename+"", function (error, stdout, stderr) { 439 | console.log('stdout: ' + stdout); 440 | console.log('stderr: ' + stderr); 441 | //if (error !== null) console.warn('exec error: ' + error); 442 | });*/ 443 | 444 | 445 | 446 | var cflags = "-mlittle-endian -mthumb -mthumb-interwork "; 447 | switch (options.boardInfo.cpu) { 448 | case "cortexm3" : cflags += "-mcpu=cortex-m3 -mfix-cortex-m3-ldrd "; break; 449 | case "cortexm4" : cflags += "-mcpu=cortex-m4 "; break; 450 | default: 451 | console.warn('Unknown CPU! ' + options.boardInfo.cpu); 452 | } 453 | /* Specifies which floating-point ABI to use. Permissible values are: ‘soft’, ‘softfp’ and ‘hard’. 454 | Specifying ‘soft’ causes GCC to generate output containing library calls for floating-point operations. 455 | ‘softfp’ allows the generation of code using hardware floating-point instructions, but still uses the soft-float calling conventions. 456 | ‘hard’ allows generation of floating-point instructions and uses FPU-specific calling conventions. */ 457 | if (options.boardInfo.cpu == "cortexm3") 458 | cflags += "-mfloat-abi=soft -mfpu=fpv4-sp-d16 "; // cortex m3 doesn't have an FPU 459 | else 460 | cflags += "-mfloat-abi=softfp -mfpu=fpv4-sp-d16 "; // everything else, try and use it 461 | cflags += "-nostdinc -nostdlib "; 462 | cflags += "-fno-common -fno-exceptions -fdata-sections -ffunction-sections "; 463 | cflags += "-flto -fno-fat-lto-objects -Wl,--allow-multiple-definition "; 464 | cflags += "-fpic -fpie "; 465 | cflags += "-fpermissive "; // for (int i=0;...);return i; 466 | cflags += "-fpreprocessed "; // disable preprocessing 467 | cflags += "-std=c++17 "; 468 | cflags += "-Os "; 469 | cflags += "-Tinc/linker.ld "; 470 | 471 | exec("arm-none-eabi-gcc "+cflags+" "+filename+".cpp -o "+filename+".elf", function (error, stdout, stderr) { 472 | require("fs").unlinkSync(filename+".cpp"); 473 | if (stdout) console.log('gcc stdout: ' + stdout+"\n"); 474 | if (stderr) console.log('gcc stderr: ' + stderr+"\n"); 475 | if (error !== null) { 476 | console.warn('exec error: ' + error); 477 | var e = error.toString(); 478 | callback(e.substr(e.indexOf("\n")+1)); 479 | } else { 480 | // -x = symbol table 481 | // -D = all sections 482 | exec("arm-none-eabi-objdump -S -D "+filename+".elf", function (error, stdout, stderr) { 483 | if (stdout) console.log('objdump stdout: ' + stdout+"\n"); 484 | if (stderr) console.log('objdump stderr: ' + stderr+"\n"); 485 | }); 486 | exec("arm-none-eabi-objcopy -O binary "+filename+".elf "+filename+".bin", function (error, stdout, stderr) { 487 | if (stdout) console.log('objcopy stdout: ' + stdout+"\n"); 488 | if (stderr) console.log('objcopy stderr: ' + stderr+"\n"); 489 | var bin = require("fs").readFileSync(filename+".bin"); 490 | require("fs").unlinkSync(filename+".bin"); 491 | require("fs").unlinkSync(filename+".elf"); 492 | 493 | callback(null, { binary : bin }); 494 | }); 495 | } 496 | }); 497 | 498 | return cCode; 499 | }; 500 | 501 | exports.compileCFunction = function(code, options, callback) { 502 | // handle entrypoints 503 | var entryPoints = []; 504 | var entrySpecs = []; 505 | var lines = code.trim().split("\n"); 506 | for (var i=0;i " + type, node, (new Error()).stack]); 12 | node.varType = type; 13 | } 14 | } 15 | function getType(node) { 16 | if (forceUndefined && !node.varType) 17 | return "JsVar"; 18 | return node.varType; 19 | } 20 | 21 | var varTypes = {}; 22 | function updateVarType(name, type, node) { 23 | if (type===undefined) return; 24 | if (varTypes[name]===undefined) { 25 | varTypes[name] = type; 26 | } else { 27 | varTypes[name] = utils.maxType(varTypes[name], type); 28 | } 29 | } 30 | 31 | // Look for assigns/inits to basic variables 32 | acorn_walk.simple(node, { 33 | "AssignmentExpression" : function (node) { 34 | if (node.left.type == "Identifier") { 35 | // if not declared first, it's pulled in from interpreter so is a JsVar 36 | if (varTypes[node.left.name] === undefined) 37 | varTypes[node.left.name] = "JsVar"; 38 | updateVarType(node.left.name, getType(node.right), node); 39 | } 40 | }, 41 | "VariableDeclaration" : function (node) { 42 | node.declarations.forEach(function(node) { 43 | if (node.init) 44 | updateVarType(node.id.name, getType(node.init), node); 45 | }); 46 | } 47 | }); 48 | /* Any identified that's just mentioned needs to be loaded from 49 | the interpreter, so is def. a JsVar */ 50 | acorn_walk.simple(node, { 51 | "Identifier" : function (node) { 52 | if (varTypes[node.name] === undefined) 53 | varTypes[node.name] = "JsVar"; 54 | } 55 | }); 56 | 57 | acorn_walk.simple(node, { 58 | "Identifier" : function(node) { 59 | if (varTypes[node.name]!==undefined) 60 | setType(node, varTypes[node.name]); 61 | else if (forceUndefined) { 62 | varTypes[node.name] = "JsVar"; 63 | setType(node, varTypes[node.name]); 64 | } 65 | }, 66 | "Literal" : function(node) { 67 | node.isNotAName = true; 68 | if (utils.isInt(node.value)) setType(node, "int"); 69 | else if (utils.isBool(node.value)) setType(node, "bool"); 70 | else setType(node, "JsVar"); 71 | }, 72 | "UnaryExpression" : function(node) { 73 | if (node.operator == "!") { 74 | node.isNotAName = true; 75 | setType(node, "bool"); 76 | } else if (node.operator == "~") { 77 | node.isNotAName = true; 78 | setType(node, "int"); 79 | } else if (node.operator == "+" || node.operator == "-") { 80 | node.isNotAName = true; 81 | if (getType(node.argument)=="int") setType(node, "int"); 82 | } 83 | }, 84 | "BinaryExpression" : function(node) { 85 | node.isNotAName = true; 86 | var boolExprs = ["==","===","!=","!==","<","<=",">",">="]; 87 | var intExprs = ["&","|","^"]; 88 | var floatExprs = ["/"]; 89 | if (boolExprs.indexOf(node.operator)>=0) setType(node, "bool"); 90 | else if (intExprs.indexOf(node.operator)>=0) setType(node, "int"); 91 | else if (floatExprs.indexOf(node.operator)>=0) setType(node, "JsVar"); 92 | else { // normal operator - do type promotion 93 | setType(node, utils.maxType(getType(node.left), getType(node.right))); 94 | } 95 | }, 96 | "LogicalExpression" : function(node) { 97 | setType(node, utils.maxType(getType(node.left), getType(node.right))); 98 | }, 99 | "ConditionalExpression" : function(node) { 100 | node.isNotAName = true; 101 | setType(node.test, "bool"); 102 | setType(node, utils.maxType(getType(node.consequent), getType(node.alternate))); 103 | }, 104 | "CallExpression" : function(node) { 105 | // handle built-in peek and poke return values. compile.js will then 106 | // add the code for these 'inline' 107 | if (node.callee.type == "Identifier" && 108 | ["peek8","peek16","peek32"].indexOf(node.callee.name)>=0 && 109 | node.arguments.length==1) { 110 | //setType(node.arguments[0],"int"); 111 | setType(node, "int"); 112 | } 113 | if (node.callee.type == "Identifier" && 114 | ["poke8","poke16","poke32"].indexOf(node.callee.name)>=0 && 115 | node.arguments.length==2 && 116 | ["int","bool"].indexOf(getType(node.arguments[1]))>=0) { 117 | //setType(node.arguments[0],"int"); 118 | setType(node, "void"); 119 | } 120 | }, 121 | "IfStatement" : function(node) { 122 | }, 123 | "WhileStatement" : function(node) { 124 | }, 125 | "ForStatement" : function(node) { 126 | }, 127 | "AssignmentExpression" : function (node) { 128 | }, 129 | "VariableDeclaration" : function (node) { 130 | node.declarations.forEach(function(node) { 131 | if (varTypes[node.id.name]!==undefined) 132 | setType(node.id, varTypes[node.id.name]); 133 | }); 134 | } 135 | }); 136 | if (modified) { 137 | console.log("Modified "+JSON.stringify(modified,null,2)); 138 | } else { 139 | console.log("Variable types: "+JSON.stringify(varTypes,null,2)); 140 | } 141 | 142 | return modified!==undefined; 143 | } 144 | 145 | exports.infer = function(node) { 146 | // Try and work out types without forcing anything 147 | tries = 20; 148 | while (infer(node, false) && tries--); 149 | if (tries<=0) throw new Error("Infer(unforced) kept changing stuff"); 150 | // now just assume that anything we're not sure about is a JsVar 151 | tries = 20; 152 | while (infer(node, true) && tries--); 153 | if (tries<=0) throw new Error("Infer(forced) kept changing stuff"); 154 | 155 | 156 | // now output 157 | console.log(JSON.stringify(node,null,2)); 158 | } 159 | -------------------------------------------------------------------------------- /src/math.js: -------------------------------------------------------------------------------- 1 | exports.cortexm4 = ` 2 | 3 | namespace std 4 | { 5 | typedef unsigned int size_t; 6 | typedef int ptrdiff_t; 7 | typedef decltype(nullptr) nullptr_t; 8 | } 9 | namespace std 10 | { 11 | inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } 12 | } 13 | namespace __gnu_cxx 14 | { 15 | inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } 16 | } 17 | extern "C++" { 18 | namespace std __attribute__ ((__visibility__ ("default"))) 19 | { 20 | struct __true_type { }; 21 | struct __false_type { }; 22 | template 23 | struct __truth_type 24 | { typedef __false_type __type; }; 25 | template<> 26 | struct __truth_type 27 | { typedef __true_type __type; }; 28 | template 29 | struct __traitor 30 | { 31 | enum { __value = bool(_Sp::__value) || bool(_Tp::__value) }; 32 | typedef typename __truth_type<__value>::__type __type; 33 | }; 34 | template 35 | struct __are_same 36 | { 37 | enum { __value = 0 }; 38 | typedef __false_type __type; 39 | }; 40 | template 41 | struct __are_same<_Tp, _Tp> 42 | { 43 | enum { __value = 1 }; 44 | typedef __true_type __type; 45 | }; 46 | template 47 | struct __is_void 48 | { 49 | enum { __value = 0 }; 50 | typedef __false_type __type; 51 | }; 52 | template<> 53 | struct __is_void 54 | { 55 | enum { __value = 1 }; 56 | typedef __true_type __type; 57 | }; 58 | template 59 | struct __is_integer 60 | { 61 | enum { __value = 0 }; 62 | typedef __false_type __type; 63 | }; 64 | template<> 65 | struct __is_integer 66 | { 67 | enum { __value = 1 }; 68 | typedef __true_type __type; 69 | }; 70 | template<> 71 | struct __is_integer 72 | { 73 | enum { __value = 1 }; 74 | typedef __true_type __type; 75 | }; 76 | template<> 77 | struct __is_integer 78 | { 79 | enum { __value = 1 }; 80 | typedef __true_type __type; 81 | }; 82 | template<> 83 | struct __is_integer 84 | { 85 | enum { __value = 1 }; 86 | typedef __true_type __type; 87 | }; 88 | template<> 89 | struct __is_integer 90 | { 91 | enum { __value = 1 }; 92 | typedef __true_type __type; 93 | }; 94 | template<> 95 | struct __is_integer 96 | { 97 | enum { __value = 1 }; 98 | typedef __true_type __type; 99 | }; 100 | template<> 101 | struct __is_integer 102 | { 103 | enum { __value = 1 }; 104 | typedef __true_type __type; 105 | }; 106 | template<> 107 | struct __is_integer 108 | { 109 | enum { __value = 1 }; 110 | typedef __true_type __type; 111 | }; 112 | template<> 113 | struct __is_integer 114 | { 115 | enum { __value = 1 }; 116 | typedef __true_type __type; 117 | }; 118 | template<> 119 | struct __is_integer 120 | { 121 | enum { __value = 1 }; 122 | typedef __true_type __type; 123 | }; 124 | template<> 125 | struct __is_integer 126 | { 127 | enum { __value = 1 }; 128 | typedef __true_type __type; 129 | }; 130 | template<> 131 | struct __is_integer 132 | { 133 | enum { __value = 1 }; 134 | typedef __true_type __type; 135 | }; 136 | template<> 137 | struct __is_integer 138 | { 139 | enum { __value = 1 }; 140 | typedef __true_type __type; 141 | }; 142 | template<> 143 | struct __is_integer 144 | { 145 | enum { __value = 1 }; 146 | typedef __true_type __type; 147 | }; 148 | template<> 149 | struct __is_integer 150 | { 151 | enum { __value = 1 }; 152 | typedef __true_type __type; 153 | }; 154 | template 155 | struct __is_floating 156 | { 157 | enum { __value = 0 }; 158 | typedef __false_type __type; 159 | }; 160 | template<> 161 | struct __is_floating 162 | { 163 | enum { __value = 1 }; 164 | typedef __true_type __type; 165 | }; 166 | template<> 167 | struct __is_floating 168 | { 169 | enum { __value = 1 }; 170 | typedef __true_type __type; 171 | }; 172 | template<> 173 | struct __is_floating 174 | { 175 | enum { __value = 1 }; 176 | typedef __true_type __type; 177 | }; 178 | template 179 | struct __is_pointer 180 | { 181 | enum { __value = 0 }; 182 | typedef __false_type __type; 183 | }; 184 | template 185 | struct __is_pointer<_Tp*> 186 | { 187 | enum { __value = 1 }; 188 | typedef __true_type __type; 189 | }; 190 | template 191 | struct __is_arithmetic 192 | : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > 193 | { }; 194 | template 195 | struct __is_scalar 196 | : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > 197 | { }; 198 | template 199 | struct __is_char 200 | { 201 | enum { __value = 0 }; 202 | typedef __false_type __type; 203 | }; 204 | template<> 205 | struct __is_char 206 | { 207 | enum { __value = 1 }; 208 | typedef __true_type __type; 209 | }; 210 | template<> 211 | struct __is_char 212 | { 213 | enum { __value = 1 }; 214 | typedef __true_type __type; 215 | }; 216 | template 217 | struct __is_byte 218 | { 219 | enum { __value = 0 }; 220 | typedef __false_type __type; 221 | }; 222 | template<> 223 | struct __is_byte 224 | { 225 | enum { __value = 1 }; 226 | typedef __true_type __type; 227 | }; 228 | template<> 229 | struct __is_byte 230 | { 231 | enum { __value = 1 }; 232 | typedef __true_type __type; 233 | }; 234 | template<> 235 | struct __is_byte 236 | { 237 | enum { __value = 1 }; 238 | typedef __true_type __type; 239 | }; 240 | template struct iterator_traits; 241 | template 242 | struct __is_nonvolatile_trivially_copyable 243 | { 244 | enum { __value = __is_trivially_copyable(_Tp) }; 245 | }; 246 | template 247 | struct __is_nonvolatile_trivially_copyable 248 | { 249 | enum { __value = 0 }; 250 | }; 251 | template 252 | struct __memcpyable 253 | { 254 | enum { __value = 0 }; 255 | }; 256 | template 257 | struct __memcpyable<_Tp*, _Tp*> 258 | : __is_nonvolatile_trivially_copyable<_Tp> 259 | { }; 260 | template 261 | struct __memcpyable<_Tp*, const _Tp*> 262 | : __is_nonvolatile_trivially_copyable<_Tp> 263 | { }; 264 | template 265 | struct __memcmpable 266 | { 267 | enum { __value = 0 }; 268 | }; 269 | template 270 | struct __memcmpable<_Tp*, _Tp*> 271 | : __is_nonvolatile_trivially_copyable<_Tp> 272 | { }; 273 | template 274 | struct __memcmpable 275 | : __is_nonvolatile_trivially_copyable<_Tp> 276 | { }; 277 | template 278 | struct __memcmpable<_Tp*, const _Tp*> 279 | : __is_nonvolatile_trivially_copyable<_Tp> 280 | { }; 281 | template::__value> 282 | struct __is_memcmp_ordered 283 | { 284 | static const bool __value = _Tp(-1) > _Tp(1); 285 | }; 286 | template 287 | struct __is_memcmp_ordered<_Tp, false> 288 | { 289 | static const bool __value = false; 290 | }; 291 | template 292 | struct __is_memcmp_ordered_with 293 | { 294 | static const bool __value = __is_memcmp_ordered<_Tp>::__value 295 | && __is_memcmp_ordered<_Up>::__value; 296 | }; 297 | template 298 | struct __is_memcmp_ordered_with<_Tp, _Up, false> 299 | { 300 | static const bool __value = false; 301 | }; 302 | template 303 | struct __is_move_iterator 304 | { 305 | enum { __value = 0 }; 306 | typedef __false_type __type; 307 | }; 308 | template 309 | inline _Iterator 310 | __miter_base(_Iterator __it) 311 | { return __it; } 312 | } 313 | } 314 | extern "C++" { 315 | namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) 316 | { 317 | template 318 | struct __enable_if 319 | { }; 320 | template 321 | struct __enable_if 322 | { typedef _Tp __type; }; 323 | template 324 | struct __conditional_type 325 | { typedef _Iftrue __type; }; 326 | template 327 | struct __conditional_type 328 | { typedef _Iffalse __type; }; 329 | template 330 | struct __add_unsigned 331 | { 332 | private: 333 | typedef __enable_if::__value, _Tp> __if_type; 334 | public: 335 | typedef typename __if_type::__type __type; 336 | }; 337 | template<> 338 | struct __add_unsigned 339 | { typedef unsigned char __type; }; 340 | template<> 341 | struct __add_unsigned 342 | { typedef unsigned char __type; }; 343 | template<> 344 | struct __add_unsigned 345 | { typedef unsigned short __type; }; 346 | template<> 347 | struct __add_unsigned 348 | { typedef unsigned int __type; }; 349 | template<> 350 | struct __add_unsigned 351 | { typedef unsigned long __type; }; 352 | template<> 353 | struct __add_unsigned 354 | { typedef unsigned long long __type; }; 355 | template<> 356 | struct __add_unsigned; 357 | template<> 358 | struct __add_unsigned; 359 | template 360 | struct __remove_unsigned 361 | { 362 | private: 363 | typedef __enable_if::__value, _Tp> __if_type; 364 | public: 365 | typedef typename __if_type::__type __type; 366 | }; 367 | template<> 368 | struct __remove_unsigned 369 | { typedef signed char __type; }; 370 | template<> 371 | struct __remove_unsigned 372 | { typedef signed char __type; }; 373 | template<> 374 | struct __remove_unsigned 375 | { typedef short __type; }; 376 | template<> 377 | struct __remove_unsigned 378 | { typedef int __type; }; 379 | template<> 380 | struct __remove_unsigned 381 | { typedef long __type; }; 382 | template<> 383 | struct __remove_unsigned 384 | { typedef long long __type; }; 385 | template<> 386 | struct __remove_unsigned; 387 | template<> 388 | struct __remove_unsigned; 389 | template 390 | inline bool 391 | __is_null_pointer(_Type* __ptr) 392 | { return __ptr == 0; } 393 | template 394 | inline bool 395 | __is_null_pointer(_Type) 396 | { return false; } 397 | inline bool 398 | __is_null_pointer(std::nullptr_t) 399 | { return true; } 400 | template::__value> 401 | struct __promote 402 | { typedef double __type; }; 403 | template 404 | struct __promote<_Tp, false> 405 | { }; 406 | template<> 407 | struct __promote 408 | { typedef long double __type; }; 409 | template<> 410 | struct __promote 411 | { typedef double __type; }; 412 | template<> 413 | struct __promote 414 | { typedef float __type; }; 415 | template::__type, 417 | typename _Up2 = typename __promote<_Up>::__type> 418 | struct __promote_2 419 | { 420 | typedef __typeof__(_Tp2() + _Up2()) __type; 421 | }; 422 | template::__type, 424 | typename _Up2 = typename __promote<_Up>::__type, 425 | typename _Vp2 = typename __promote<_Vp>::__type> 426 | struct __promote_3 427 | { 428 | typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type; 429 | }; 430 | template::__type, 432 | typename _Up2 = typename __promote<_Up>::__type, 433 | typename _Vp2 = typename __promote<_Vp>::__type, 434 | typename _Wp2 = typename __promote<_Wp>::__type> 435 | struct __promote_4 436 | { 437 | typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type; 438 | }; 439 | } 440 | } 441 | extern "C" { 442 | extern "C" { 443 | } 444 | typedef int ptrdiff_t; 445 | typedef unsigned int size_t; 446 | typedef struct { 447 | long long __max_align_ll __attribute__((__aligned__(__alignof__(long long)))); 448 | long double __max_align_ld __attribute__((__aligned__(__alignof__(long double)))); 449 | } max_align_t; 450 | typedef decltype(nullptr) nullptr_t; 451 | typedef unsigned int wint_t; 452 | extern "C" { 453 | typedef signed char __int8_t; 454 | typedef unsigned char __uint8_t; 455 | typedef short int __int16_t; 456 | typedef short unsigned int __uint16_t; 457 | typedef long int __int32_t; 458 | typedef long unsigned int __uint32_t; 459 | typedef long long int __int64_t; 460 | typedef long long unsigned int __uint64_t; 461 | typedef signed char __int_least8_t; 462 | typedef unsigned char __uint_least8_t; 463 | typedef short int __int_least16_t; 464 | typedef short unsigned int __uint_least16_t; 465 | typedef long int __int_least32_t; 466 | typedef long unsigned int __uint_least32_t; 467 | typedef long long int __int_least64_t; 468 | typedef long long unsigned int __uint_least64_t; 469 | typedef long long int __intmax_t; 470 | typedef long long unsigned int __uintmax_t; 471 | typedef int __intptr_t; 472 | typedef unsigned int __uintptr_t; 473 | } 474 | typedef long __blkcnt_t; 475 | typedef long __blksize_t; 476 | typedef __uint64_t __fsblkcnt_t; 477 | typedef __uint32_t __fsfilcnt_t; 478 | typedef long _off_t; 479 | typedef int __pid_t; 480 | typedef short __dev_t; 481 | typedef unsigned short __uid_t; 482 | typedef unsigned short __gid_t; 483 | typedef __uint32_t __id_t; 484 | typedef unsigned short __ino_t; 485 | typedef __uint32_t __mode_t; 486 | __extension__ typedef long long _off64_t; 487 | typedef _off_t __off_t; 488 | typedef _off64_t __loff_t; 489 | typedef long __key_t; 490 | typedef long _fpos_t; 491 | typedef unsigned int __size_t; 492 | typedef signed int _ssize_t; 493 | typedef _ssize_t __ssize_t; 494 | typedef struct 495 | { 496 | int __count; 497 | union 498 | { 499 | wint_t __wch; 500 | unsigned char __wchb[4]; 501 | } __value; 502 | } _mbstate_t; 503 | typedef void *_iconv_t; 504 | typedef unsigned long __clock_t; 505 | typedef __int_least64_t __time_t; 506 | typedef unsigned long __clockid_t; 507 | typedef unsigned long __timer_t; 508 | typedef __uint8_t __sa_family_t; 509 | typedef __uint32_t __socklen_t; 510 | typedef int __nl_item; 511 | typedef unsigned short __nlink_t; 512 | typedef long __suseconds_t; 513 | typedef unsigned long __useconds_t; 514 | typedef __builtin_va_list __va_list; 515 | typedef unsigned long __ULong; 516 | extern "C" { 517 | struct __lock; 518 | typedef struct __lock * _LOCK_T; 519 | extern void __retarget_lock_init(_LOCK_T *lock); 520 | extern void __retarget_lock_init_recursive(_LOCK_T *lock); 521 | extern void __retarget_lock_close(_LOCK_T lock); 522 | extern void __retarget_lock_close_recursive(_LOCK_T lock); 523 | extern void __retarget_lock_acquire(_LOCK_T lock); 524 | extern void __retarget_lock_acquire_recursive(_LOCK_T lock); 525 | extern int __retarget_lock_try_acquire(_LOCK_T lock); 526 | extern int __retarget_lock_try_acquire_recursive(_LOCK_T lock); 527 | extern void __retarget_lock_release(_LOCK_T lock); 528 | extern void __retarget_lock_release_recursive(_LOCK_T lock); 529 | } 530 | typedef _LOCK_T _flock_t; 531 | struct _reent; 532 | struct __locale_t; 533 | struct _Bigint 534 | { 535 | struct _Bigint *_next; 536 | int _k, _maxwds, _sign, _wds; 537 | __ULong _x[1]; 538 | }; 539 | struct __tm 540 | { 541 | int __tm_sec; 542 | int __tm_min; 543 | int __tm_hour; 544 | int __tm_mday; 545 | int __tm_mon; 546 | int __tm_year; 547 | int __tm_wday; 548 | int __tm_yday; 549 | int __tm_isdst; 550 | }; 551 | struct _on_exit_args { 552 | void * _fnargs[32]; 553 | void * _dso_handle[32]; 554 | __ULong _fntypes; 555 | __ULong _is_cxa; 556 | }; 557 | struct _atexit { 558 | struct _atexit *_next; 559 | int _ind; 560 | void (*_fns[32])(void); 561 | struct _on_exit_args _on_exit_args; 562 | }; 563 | struct __sbuf { 564 | unsigned char *_base; 565 | int _size; 566 | }; 567 | struct __sFILE { 568 | unsigned char *_p; 569 | int _r; 570 | int _w; 571 | short _flags; 572 | short _file; 573 | struct __sbuf _bf; 574 | int _lbfsize; 575 | void * _cookie; 576 | int (*_read) (struct _reent *, void *, 577 | char *, int); 578 | int (*_write) (struct _reent *, void *, 579 | const char *, 580 | int); 581 | _fpos_t (*_seek) (struct _reent *, void *, _fpos_t, int); 582 | int (*_close) (struct _reent *, void *); 583 | struct __sbuf _ub; 584 | unsigned char *_up; 585 | int _ur; 586 | unsigned char _ubuf[3]; 587 | unsigned char _nbuf[1]; 588 | struct __sbuf _lb; 589 | int _blksize; 590 | _off_t _offset; 591 | struct _reent *_data; 592 | _flock_t _lock; 593 | _mbstate_t _mbstate; 594 | int _flags2; 595 | }; 596 | typedef struct __sFILE __FILE; 597 | struct _glue 598 | { 599 | struct _glue *_next; 600 | int _niobs; 601 | __FILE *_iobs; 602 | }; 603 | struct _rand48 { 604 | unsigned short _seed[3]; 605 | unsigned short _mult[3]; 606 | unsigned short _add; 607 | }; 608 | struct _reent 609 | { 610 | int _errno; 611 | __FILE *_stdin, *_stdout, *_stderr; 612 | int _inc; 613 | char _emergency[25]; 614 | int _unspecified_locale_info; 615 | struct __locale_t *_locale; 616 | int __sdidinit; 617 | void (*__cleanup) (struct _reent *); 618 | struct _Bigint *_result; 619 | int _result_k; 620 | struct _Bigint *_p5s; 621 | struct _Bigint **_freelist; 622 | int _cvtlen; 623 | char *_cvtbuf; 624 | union 625 | { 626 | struct 627 | { 628 | unsigned int _unused_rand; 629 | char * _strtok_last; 630 | char _asctime_buf[26]; 631 | struct __tm _localtime_buf; 632 | int _gamma_signgam; 633 | __extension__ unsigned long long _rand_next; 634 | struct _rand48 _r48; 635 | _mbstate_t _mblen_state; 636 | _mbstate_t _mbtowc_state; 637 | _mbstate_t _wctomb_state; 638 | char _l64a_buf[8]; 639 | char _signal_buf[24]; 640 | int _getdate_err; 641 | _mbstate_t _mbrlen_state; 642 | _mbstate_t _mbrtowc_state; 643 | _mbstate_t _mbsrtowcs_state; 644 | _mbstate_t _wcrtomb_state; 645 | _mbstate_t _wcsrtombs_state; 646 | int _h_errno; 647 | } _reent; 648 | struct 649 | { 650 | unsigned char * _nextf[30]; 651 | unsigned int _nmalloc[30]; 652 | } _unused; 653 | } _new; 654 | struct _atexit *_atexit; 655 | struct _atexit _atexit0; 656 | void (**(_sig_func))(int); 657 | struct _glue __sglue; 658 | __FILE __sf[3]; 659 | }; 660 | extern struct _reent *_impure_ptr ; 661 | extern struct _reent *const _global_impure_ptr ; 662 | void _reclaim_reent (struct _reent *); 663 | } 664 | extern "C" { 665 | extern double atan (double); 666 | extern double cos (double); 667 | extern double sin (double); 668 | extern double tan (double); 669 | extern double tanh (double); 670 | extern double frexp (double, int *); 671 | extern double modf (double, double *); 672 | extern double ceil (double); 673 | extern double fabs (double); 674 | extern double floor (double); 675 | extern double acos (double); 676 | extern double asin (double); 677 | extern double atan2 (double, double); 678 | extern double cosh (double); 679 | extern double sinh (double); 680 | extern double exp (double); 681 | extern double ldexp (double, int); 682 | extern double log (double); 683 | extern double log10 (double); 684 | extern double pow (double, double); 685 | extern double sqrt (double); 686 | extern double fmod (double, double); 687 | extern int finite (double); 688 | extern int finitef (float); 689 | extern int finitel (long double); 690 | extern int isinff (float); 691 | extern int isnanf (float); 692 | typedef float float_t; 693 | typedef double double_t; 694 | extern int __isinff (float); 695 | extern int __isinfd (double); 696 | extern int __isnanf (float); 697 | extern int __isnand (double); 698 | extern int __fpclassifyf (float); 699 | extern int __fpclassifyd (double); 700 | extern int __signbitf (float); 701 | extern int __signbitd (double); 702 | extern double infinity (void); 703 | extern double nan (const char *); 704 | extern double copysign (double, double); 705 | extern double logb (double); 706 | extern int ilogb (double); 707 | extern double asinh (double); 708 | extern double cbrt (double); 709 | extern double nextafter (double, double); 710 | extern double rint (double); 711 | extern double scalbn (double, int); 712 | extern double exp2 (double); 713 | extern double scalbln (double, long int); 714 | extern double tgamma (double); 715 | extern double nearbyint (double); 716 | extern long int lrint (double); 717 | extern long long int llrint (double); 718 | extern double round (double); 719 | extern long int lround (double); 720 | extern long long int llround (double); 721 | extern double trunc (double); 722 | extern double remquo (double, double, int *); 723 | extern double fdim (double, double); 724 | extern double fmax (double, double); 725 | extern double fmin (double, double); 726 | extern double fma (double, double, double); 727 | extern double log1p (double); 728 | extern double expm1 (double); 729 | extern double acosh (double); 730 | extern double atanh (double); 731 | extern double remainder (double, double); 732 | extern double gamma (double); 733 | extern double lgamma (double); 734 | extern double erf (double); 735 | extern double erfc (double); 736 | extern double log2 (double); 737 | extern double hypot (double, double); 738 | extern float atanf (float); 739 | extern float cosf (float); 740 | extern float sinf (float); 741 | extern float tanf (float); 742 | extern float tanhf (float); 743 | extern float frexpf (float, int *); 744 | extern float modff (float, float *); 745 | extern float ceilf (float); 746 | extern float fabsf (float); 747 | extern float floorf (float); 748 | extern float acosf (float); 749 | extern float asinf (float); 750 | extern float atan2f (float, float); 751 | extern float coshf (float); 752 | extern float sinhf (float); 753 | extern float expf (float); 754 | extern float ldexpf (float, int); 755 | extern float logf (float); 756 | extern float log10f (float); 757 | extern float powf (float, float); 758 | extern float sqrtf (float); 759 | extern float fmodf (float, float); 760 | extern float exp2f (float); 761 | extern float scalblnf (float, long int); 762 | extern float tgammaf (float); 763 | extern float nearbyintf (float); 764 | extern long int lrintf (float); 765 | extern long long int llrintf (float); 766 | extern float roundf (float); 767 | extern long int lroundf (float); 768 | extern long long int llroundf (float); 769 | extern float truncf (float); 770 | extern float remquof (float, float, int *); 771 | extern float fdimf (float, float); 772 | extern float fmaxf (float, float); 773 | extern float fminf (float, float); 774 | extern float fmaf (float, float, float); 775 | extern float infinityf (void); 776 | extern float nanf (const char *); 777 | extern float copysignf (float, float); 778 | extern float logbf (float); 779 | extern int ilogbf (float); 780 | extern float asinhf (float); 781 | extern float cbrtf (float); 782 | extern float nextafterf (float, float); 783 | extern float rintf (float); 784 | extern float scalbnf (float, int); 785 | extern float log1pf (float); 786 | extern float expm1f (float); 787 | extern float acoshf (float); 788 | extern float atanhf (float); 789 | extern float remainderf (float, float); 790 | extern float gammaf (float); 791 | extern float lgammaf (float); 792 | extern float erff (float); 793 | extern float erfcf (float); 794 | extern float log2f (float); 795 | extern float hypotf (float, float); 796 | extern long double atanl (long double); 797 | extern long double cosl (long double); 798 | extern long double sinl (long double); 799 | extern long double tanl (long double); 800 | extern long double tanhl (long double); 801 | extern long double frexpl (long double, int *); 802 | extern long double modfl (long double, long double *); 803 | extern long double ceill (long double); 804 | extern long double fabsl (long double); 805 | extern long double floorl (long double); 806 | extern long double log1pl (long double); 807 | extern long double expm1l (long double); 808 | extern long double acosl (long double); 809 | extern long double asinl (long double); 810 | extern long double atan2l (long double, long double); 811 | extern long double coshl (long double); 812 | extern long double sinhl (long double); 813 | extern long double expl (long double); 814 | extern long double ldexpl (long double, int); 815 | extern long double logl (long double); 816 | extern long double log10l (long double); 817 | extern long double powl (long double, long double); 818 | extern long double sqrtl (long double); 819 | extern long double fmodl (long double, long double); 820 | extern long double hypotl (long double, long double); 821 | extern long double copysignl (long double, long double); 822 | extern long double nanl (const char *); 823 | extern int ilogbl (long double); 824 | extern long double asinhl (long double); 825 | extern long double cbrtl (long double); 826 | extern long double nextafterl (long double, long double); 827 | extern float nexttowardf (float, long double); 828 | extern double nexttoward (double, long double); 829 | extern long double nexttowardl (long double, long double); 830 | extern long double logbl (long double); 831 | extern long double log2l (long double); 832 | extern long double rintl (long double); 833 | extern long double scalbnl (long double, int); 834 | extern long double exp2l (long double); 835 | extern long double scalblnl (long double, long); 836 | extern long double tgammal (long double); 837 | extern long double nearbyintl (long double); 838 | extern long int lrintl (long double); 839 | extern long long int llrintl (long double); 840 | extern long double roundl (long double); 841 | extern long lroundl (long double); 842 | extern long long int llroundl (long double); 843 | extern long double truncl (long double); 844 | extern long double remquol (long double, long double, int *); 845 | extern long double fdiml (long double, long double); 846 | extern long double fmaxl (long double, long double); 847 | extern long double fminl (long double, long double); 848 | extern long double fmal (long double, long double, long double); 849 | extern long double acoshl (long double); 850 | extern long double atanhl (long double); 851 | extern long double remainderl (long double, long double); 852 | extern long double lgammal (long double); 853 | extern long double erfl (long double); 854 | extern long double erfcl (long double); 855 | extern double drem (double, double); 856 | extern float dremf (float, float); 857 | extern double gamma_r (double, int *); 858 | extern double lgamma_r (double, int *); 859 | extern float gammaf_r (float, int *); 860 | extern float lgammaf_r (float, int *); 861 | extern double y0 (double); 862 | extern double y1 (double); 863 | extern double yn (int, double); 864 | extern double j0 (double); 865 | extern double j1 (double); 866 | extern double jn (int, double); 867 | extern float y0f (float); 868 | extern float y1f (float); 869 | extern float ynf (int, float); 870 | extern float j0f (float); 871 | extern float j1f (float); 872 | extern float jnf (int, float); 873 | extern int *__signgam (void); 874 | } 875 | 876 | extern "C" { 877 | typedef struct 878 | { 879 | int quot; 880 | int rem; 881 | } div_t; 882 | typedef struct 883 | { 884 | long quot; 885 | long rem; 886 | } ldiv_t; 887 | typedef struct 888 | { 889 | long long int quot; 890 | long long int rem; 891 | } lldiv_t; 892 | typedef int (*__compar_fn_t) (const void *, const void *); 893 | int __locale_mb_cur_max (void); 894 | void abort (void) __attribute__ ((__noreturn__)); 895 | int abs (int); 896 | __uint32_t arc4random (void); 897 | __uint32_t arc4random_uniform (__uint32_t); 898 | void arc4random_buf (void *, size_t); 899 | int atexit (void (*__func)(void)); 900 | double atof (const char *__nptr); 901 | float atoff (const char *__nptr); 902 | int atoi (const char *__nptr); 903 | int _atoi_r (struct _reent *, const char *__nptr); 904 | long atol (const char *__nptr); 905 | long _atol_r (struct _reent *, const char *__nptr); 906 | void * bsearch (const void *__key, 907 | const void *__base, 908 | size_t __nmemb, 909 | size_t __size, 910 | __compar_fn_t _compar); 911 | void *calloc(size_t, size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) 912 | __attribute__((__alloc_size__(1, 2))) __attribute__ ((__nothrow__)); 913 | div_t div (int __numer, int __denom); 914 | void exit (int __status) __attribute__ ((__noreturn__)); 915 | void free (void *) __attribute__ ((__nothrow__)); 916 | char * getenv (const char *__string); 917 | char * _getenv_r (struct _reent *, const char *__string); 918 | char * _findenv (const char *, int *); 919 | char * _findenv_r (struct _reent *, const char *, int *); 920 | extern char *suboptarg; 921 | int getsubopt (char **, char * const *, char **); 922 | long labs (long); 923 | ldiv_t ldiv (long __numer, long __denom); 924 | void *malloc(size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1))) __attribute__ ((__nothrow__)); 925 | int mblen (const char *, size_t); 926 | int _mblen_r (struct _reent *, const char *, size_t, _mbstate_t *); 927 | int mbtowc (wchar_t *, const char *, size_t); 928 | int _mbtowc_r (struct _reent *, wchar_t *, const char *, size_t, _mbstate_t *); 929 | int wctomb (char *, wchar_t); 930 | int _wctomb_r (struct _reent *, char *, wchar_t, _mbstate_t *); 931 | size_t mbstowcs (wchar_t *, const char *, size_t); 932 | size_t _mbstowcs_r (struct _reent *, wchar_t *, const char *, size_t, _mbstate_t *); 933 | size_t wcstombs (char *, const wchar_t *, size_t); 934 | size_t _wcstombs_r (struct _reent *, char *, const wchar_t *, size_t, _mbstate_t *); 935 | char * mkdtemp (char *); 936 | int mkstemp (char *); 937 | int mkstemps (char *, int); 938 | char * mktemp (char *) __attribute__ ((__deprecated__("the use of \`mktemp' is dangerous; use \`mkstemp' instead"))); 939 | char * _mkdtemp_r (struct _reent *, char *); 940 | int _mkostemp_r (struct _reent *, char *, int); 941 | int _mkostemps_r (struct _reent *, char *, int, int); 942 | int _mkstemp_r (struct _reent *, char *); 943 | int _mkstemps_r (struct _reent *, char *, int); 944 | char * _mktemp_r (struct _reent *, char *) __attribute__ ((__deprecated__("the use of \`mktemp' is dangerous; use \`mkstemp' instead"))); 945 | void qsort (void *__base, size_t __nmemb, size_t __size, __compar_fn_t _compar); 946 | int rand (void); 947 | void *realloc(void *, size_t) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(2))) __attribute__ ((__nothrow__)); 948 | void *reallocarray(void *, size_t, size_t) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(2, 3))); 949 | void *reallocf(void *, size_t) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(2))); 950 | char * realpath (const char * path, char * resolved_path); 951 | int rpmatch (const char *response); 952 | void srand (unsigned __seed); 953 | double strtod (const char * __n, char ** __end_PTR); 954 | double _strtod_r (struct _reent *,const char * __n, char ** __end_PTR); 955 | float strtof (const char * __n, char ** __end_PTR); 956 | long strtol (const char * __n, char ** __end_PTR, int __base); 957 | long _strtol_r (struct _reent *,const char * __n, char ** __end_PTR, int __base); 958 | unsigned long strtoul (const char * __n, char ** __end_PTR, int __base); 959 | unsigned long _strtoul_r (struct _reent *,const char * __n, char ** __end_PTR, int __base); 960 | int system (const char *__string); 961 | long a64l (const char *__input); 962 | char * l64a (long __input); 963 | char * _l64a_r (struct _reent *,long __input); 964 | int on_exit (void (*__func)(int, void *),void *__arg); 965 | void _Exit (int __status) __attribute__ ((__noreturn__)); 966 | int putenv (char *__string); 967 | int _putenv_r (struct _reent *, char *__string); 968 | void * _reallocf_r (struct _reent *, void *, size_t); 969 | int setenv (const char *__string, const char *__value, int __overwrite); 970 | int _setenv_r (struct _reent *, const char *__string, const char *__value, int __overwrite); 971 | char * __itoa (int, char *, int); 972 | char * __utoa (unsigned, char *, int); 973 | char * itoa (int, char *, int); 974 | char * utoa (unsigned, char *, int); 975 | int rand_r (unsigned *__seed); 976 | double drand48 (void); 977 | double _drand48_r (struct _reent *); 978 | double erand48 (unsigned short [3]); 979 | double _erand48_r (struct _reent *, unsigned short [3]); 980 | long jrand48 (unsigned short [3]); 981 | long _jrand48_r (struct _reent *, unsigned short [3]); 982 | void lcong48 (unsigned short [7]); 983 | void _lcong48_r (struct _reent *, unsigned short [7]); 984 | long lrand48 (void); 985 | long _lrand48_r (struct _reent *); 986 | long mrand48 (void); 987 | long _mrand48_r (struct _reent *); 988 | long nrand48 (unsigned short [3]); 989 | long _nrand48_r (struct _reent *, unsigned short [3]); 990 | unsigned short * 991 | seed48 (unsigned short [3]); 992 | unsigned short * 993 | _seed48_r (struct _reent *, unsigned short [3]); 994 | void srand48 (long); 995 | void _srand48_r (struct _reent *, long); 996 | char * initstate (unsigned, char *, size_t); 997 | long random (void); 998 | char * setstate (char *); 999 | void srandom (unsigned); 1000 | long long atoll (const char *__nptr); 1001 | long long _atoll_r (struct _reent *, const char *__nptr); 1002 | long long llabs (long long); 1003 | lldiv_t lldiv (long long __numer, long long __denom); 1004 | long long strtoll (const char * __n, char ** __end_PTR, int __base); 1005 | long long _strtoll_r (struct _reent *, const char * __n, char ** __end_PTR, int __base); 1006 | unsigned long long strtoull (const char * __n, char ** __end_PTR, int __base); 1007 | unsigned long long _strtoull_r (struct _reent *, const char * __n, char ** __end_PTR, int __base); 1008 | void cfree (void *); 1009 | int unsetenv (const char *__string); 1010 | int _unsetenv_r (struct _reent *, const char *__string); 1011 | int posix_memalign (void **, size_t, size_t) __attribute__((__nonnull__ (1))) 1012 | __attribute__((__warn_unused_result__)); 1013 | char * _dtoa_r (struct _reent *, double, int, int, int *, int*, char**); 1014 | void * _malloc_r (struct _reent *, size_t) __attribute__ ((__nothrow__)); 1015 | void * _calloc_r (struct _reent *, size_t, size_t) __attribute__ ((__nothrow__)); 1016 | void _free_r (struct _reent *, void *) __attribute__ ((__nothrow__)); 1017 | void * _realloc_r (struct _reent *, void *, size_t) __attribute__ ((__nothrow__)); 1018 | void _mstats_r (struct _reent *, char *); 1019 | int _system_r (struct _reent *, const char *); 1020 | void __eprintf (const char *, const char *, unsigned int, const char *); 1021 | void qsort_r (void *__base, size_t __nmemb, size_t __size, void *__thunk, int (*_compar)(void *, const void *, const void *)) 1022 | __asm__ ("" "__bsd_qsort_r"); 1023 | extern long double _strtold_r (struct _reent *, const char *, char **); 1024 | extern long double strtold (const char *, char **); 1025 | void * aligned_alloc(size_t, size_t) __attribute__((__malloc__)) __attribute__((__alloc_align__(1))) 1026 | __attribute__((__alloc_size__(2))) __attribute__((__warn_unused_result__)); 1027 | int at_quick_exit(void (*)(void)); 1028 | [[noreturn]] void 1029 | quick_exit(int); 1030 | } 1031 | extern "C++" 1032 | { 1033 | namespace std __attribute__ ((__visibility__ ("default"))) 1034 | { 1035 | using ::abs; 1036 | inline long 1037 | abs(long __i) { return __builtin_labs(__i); } 1038 | inline long long 1039 | abs(long long __x) { return __builtin_llabs (__x); } 1040 | inline constexpr double 1041 | abs(double __x) 1042 | { return __builtin_fabs(__x); } 1043 | inline constexpr float 1044 | abs(float __x) 1045 | { return __builtin_fabsf(__x); } 1046 | inline constexpr long double 1047 | abs(long double __x) 1048 | { return __builtin_fabsl(__x); } 1049 | } 1050 | } 1051 | extern "C++" 1052 | { 1053 | namespace std __attribute__ ((__visibility__ ("default"))) 1054 | { 1055 | using ::acos; 1056 | inline constexpr float 1057 | acos(float __x) 1058 | { return __builtin_acosf(__x); } 1059 | inline constexpr long double 1060 | acos(long double __x) 1061 | { return __builtin_acosl(__x); } 1062 | template 1063 | inline constexpr 1064 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1065 | double>::__type 1066 | acos(_Tp __x) 1067 | { return __builtin_acos(__x); } 1068 | using ::asin; 1069 | inline constexpr float 1070 | asin(float __x) 1071 | { return __builtin_asinf(__x); } 1072 | inline constexpr long double 1073 | asin(long double __x) 1074 | { return __builtin_asinl(__x); } 1075 | template 1076 | inline constexpr 1077 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1078 | double>::__type 1079 | asin(_Tp __x) 1080 | { return __builtin_asin(__x); } 1081 | using ::atan; 1082 | inline constexpr float 1083 | atan(float __x) 1084 | { return __builtin_atanf(__x); } 1085 | inline constexpr long double 1086 | atan(long double __x) 1087 | { return __builtin_atanl(__x); } 1088 | template 1089 | inline constexpr 1090 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1091 | double>::__type 1092 | atan(_Tp __x) 1093 | { return __builtin_atan(__x); } 1094 | using ::atan2; 1095 | inline constexpr float 1096 | atan2(float __y, float __x) 1097 | { return __builtin_atan2f(__y, __x); } 1098 | inline constexpr long double 1099 | atan2(long double __y, long double __x) 1100 | { return __builtin_atan2l(__y, __x); } 1101 | template 1102 | inline constexpr 1103 | typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1104 | atan2(_Tp __y, _Up __x) 1105 | { 1106 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1107 | return atan2(__type(__y), __type(__x)); 1108 | } 1109 | using ::ceil; 1110 | inline constexpr float 1111 | ceil(float __x) 1112 | { return __builtin_ceilf(__x); } 1113 | inline constexpr long double 1114 | ceil(long double __x) 1115 | { return __builtin_ceill(__x); } 1116 | template 1117 | inline constexpr 1118 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1119 | double>::__type 1120 | ceil(_Tp __x) 1121 | { return __builtin_ceil(__x); } 1122 | using ::cos; 1123 | inline constexpr float 1124 | cos(float __x) 1125 | { return __builtin_cosf(__x); } 1126 | inline constexpr long double 1127 | cos(long double __x) 1128 | { return __builtin_cosl(__x); } 1129 | template 1130 | inline constexpr 1131 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1132 | double>::__type 1133 | cos(_Tp __x) 1134 | { return __builtin_cos(__x); } 1135 | using ::cosh; 1136 | inline constexpr float 1137 | cosh(float __x) 1138 | { return __builtin_coshf(__x); } 1139 | inline constexpr long double 1140 | cosh(long double __x) 1141 | { return __builtin_coshl(__x); } 1142 | template 1143 | inline constexpr 1144 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1145 | double>::__type 1146 | cosh(_Tp __x) 1147 | { return __builtin_cosh(__x); } 1148 | using ::exp; 1149 | inline constexpr float 1150 | exp(float __x) 1151 | { return __builtin_expf(__x); } 1152 | inline constexpr long double 1153 | exp(long double __x) 1154 | { return __builtin_expl(__x); } 1155 | template 1156 | inline constexpr 1157 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1158 | double>::__type 1159 | exp(_Tp __x) 1160 | { return __builtin_exp(__x); } 1161 | using ::fabs; 1162 | inline constexpr float 1163 | fabs(float __x) 1164 | { return __builtin_fabsf(__x); } 1165 | inline constexpr long double 1166 | fabs(long double __x) 1167 | { return __builtin_fabsl(__x); } 1168 | template 1169 | inline constexpr 1170 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1171 | double>::__type 1172 | fabs(_Tp __x) 1173 | { return __builtin_fabs(__x); } 1174 | using ::floor; 1175 | inline constexpr float 1176 | floor(float __x) 1177 | { return __builtin_floorf(__x); } 1178 | inline constexpr long double 1179 | floor(long double __x) 1180 | { return __builtin_floorl(__x); } 1181 | template 1182 | inline constexpr 1183 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1184 | double>::__type 1185 | floor(_Tp __x) 1186 | { return __builtin_floor(__x); } 1187 | using ::fmod; 1188 | inline constexpr float 1189 | fmod(float __x, float __y) 1190 | { return __builtin_fmodf(__x, __y); } 1191 | inline constexpr long double 1192 | fmod(long double __x, long double __y) 1193 | { return __builtin_fmodl(__x, __y); } 1194 | template 1195 | inline constexpr 1196 | typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1197 | fmod(_Tp __x, _Up __y) 1198 | { 1199 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1200 | return fmod(__type(__x), __type(__y)); 1201 | } 1202 | using ::frexp; 1203 | inline float 1204 | frexp(float __x, int* __exp) 1205 | { return __builtin_frexpf(__x, __exp); } 1206 | inline long double 1207 | frexp(long double __x, int* __exp) 1208 | { return __builtin_frexpl(__x, __exp); } 1209 | template 1210 | inline constexpr 1211 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1212 | double>::__type 1213 | frexp(_Tp __x, int* __exp) 1214 | { return __builtin_frexp(__x, __exp); } 1215 | using ::ldexp; 1216 | inline constexpr float 1217 | ldexp(float __x, int __exp) 1218 | { return __builtin_ldexpf(__x, __exp); } 1219 | inline constexpr long double 1220 | ldexp(long double __x, int __exp) 1221 | { return __builtin_ldexpl(__x, __exp); } 1222 | template 1223 | inline constexpr 1224 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1225 | double>::__type 1226 | ldexp(_Tp __x, int __exp) 1227 | { return __builtin_ldexp(__x, __exp); } 1228 | using ::log; 1229 | inline constexpr float 1230 | log(float __x) 1231 | { return __builtin_logf(__x); } 1232 | inline constexpr long double 1233 | log(long double __x) 1234 | { return __builtin_logl(__x); } 1235 | template 1236 | inline constexpr 1237 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1238 | double>::__type 1239 | log(_Tp __x) 1240 | { return __builtin_log(__x); } 1241 | using ::log10; 1242 | inline constexpr float 1243 | log10(float __x) 1244 | { return __builtin_log10f(__x); } 1245 | inline constexpr long double 1246 | log10(long double __x) 1247 | { return __builtin_log10l(__x); } 1248 | template 1249 | inline constexpr 1250 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1251 | double>::__type 1252 | log10(_Tp __x) 1253 | { return __builtin_log10(__x); } 1254 | using ::modf; 1255 | inline float 1256 | modf(float __x, float* __iptr) 1257 | { return __builtin_modff(__x, __iptr); } 1258 | inline long double 1259 | modf(long double __x, long double* __iptr) 1260 | { return __builtin_modfl(__x, __iptr); } 1261 | using ::pow; 1262 | inline constexpr float 1263 | pow(float __x, float __y) 1264 | { return __builtin_powf(__x, __y); } 1265 | inline constexpr long double 1266 | pow(long double __x, long double __y) 1267 | { return __builtin_powl(__x, __y); } 1268 | template 1269 | inline constexpr 1270 | typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1271 | pow(_Tp __x, _Up __y) 1272 | { 1273 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1274 | return pow(__type(__x), __type(__y)); 1275 | } 1276 | using ::sin; 1277 | inline constexpr float 1278 | sin(float __x) 1279 | { return __builtin_sinf(__x); } 1280 | inline constexpr long double 1281 | sin(long double __x) 1282 | { return __builtin_sinl(__x); } 1283 | template 1284 | inline constexpr 1285 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1286 | double>::__type 1287 | sin(_Tp __x) 1288 | { return __builtin_sin(__x); } 1289 | using ::sinh; 1290 | inline constexpr float 1291 | sinh(float __x) 1292 | { return __builtin_sinhf(__x); } 1293 | inline constexpr long double 1294 | sinh(long double __x) 1295 | { return __builtin_sinhl(__x); } 1296 | template 1297 | inline constexpr 1298 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1299 | double>::__type 1300 | sinh(_Tp __x) 1301 | { return __builtin_sinh(__x); } 1302 | using ::sqrt; 1303 | inline constexpr float 1304 | sqrt(float __x) 1305 | { return __builtin_sqrtf(__x); } 1306 | inline constexpr long double 1307 | sqrt(long double __x) 1308 | { return __builtin_sqrtl(__x); } 1309 | template 1310 | inline constexpr 1311 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1312 | double>::__type 1313 | sqrt(_Tp __x) 1314 | { return __builtin_sqrt(__x); } 1315 | using ::tan; 1316 | inline constexpr float 1317 | tan(float __x) 1318 | { return __builtin_tanf(__x); } 1319 | inline constexpr long double 1320 | tan(long double __x) 1321 | { return __builtin_tanl(__x); } 1322 | template 1323 | inline constexpr 1324 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1325 | double>::__type 1326 | tan(_Tp __x) 1327 | { return __builtin_tan(__x); } 1328 | using ::tanh; 1329 | inline constexpr float 1330 | tanh(float __x) 1331 | { return __builtin_tanhf(__x); } 1332 | inline constexpr long double 1333 | tanh(long double __x) 1334 | { return __builtin_tanhl(__x); } 1335 | template 1336 | inline constexpr 1337 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1338 | double>::__type 1339 | tanh(_Tp __x) 1340 | { return __builtin_tanh(__x); } 1341 | constexpr int 1342 | fpclassify(float __x) 1343 | { return __builtin_fpclassify(0, 1, 4, 1344 | 3, 2, __x); } 1345 | constexpr int 1346 | fpclassify(double __x) 1347 | { return __builtin_fpclassify(0, 1, 4, 1348 | 3, 2, __x); } 1349 | constexpr int 1350 | fpclassify(long double __x) 1351 | { return __builtin_fpclassify(0, 1, 4, 1352 | 3, 2, __x); } 1353 | template 1354 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1355 | int>::__type 1356 | fpclassify(_Tp __x) 1357 | { return __x != 0 ? 4 : 2; } 1358 | constexpr bool 1359 | isfinite(float __x) 1360 | { return __builtin_isfinite(__x); } 1361 | constexpr bool 1362 | isfinite(double __x) 1363 | { return __builtin_isfinite(__x); } 1364 | constexpr bool 1365 | isfinite(long double __x) 1366 | { return __builtin_isfinite(__x); } 1367 | template 1368 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1369 | bool>::__type 1370 | isfinite(_Tp __x) 1371 | { return true; } 1372 | constexpr bool 1373 | isinf(float __x) 1374 | { return __builtin_isinf(__x); } 1375 | constexpr bool 1376 | isinf(double __x) 1377 | { return __builtin_isinf(__x); } 1378 | constexpr bool 1379 | isinf(long double __x) 1380 | { return __builtin_isinf(__x); } 1381 | template 1382 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1383 | bool>::__type 1384 | isinf(_Tp __x) 1385 | { return false; } 1386 | constexpr bool 1387 | isnan(float __x) 1388 | { return __builtin_isnan(__x); } 1389 | constexpr bool 1390 | isnan(double __x) 1391 | { return __builtin_isnan(__x); } 1392 | constexpr bool 1393 | isnan(long double __x) 1394 | { return __builtin_isnan(__x); } 1395 | template 1396 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1397 | bool>::__type 1398 | isnan(_Tp __x) 1399 | { return false; } 1400 | constexpr bool 1401 | isnormal(float __x) 1402 | { return __builtin_isnormal(__x); } 1403 | constexpr bool 1404 | isnormal(double __x) 1405 | { return __builtin_isnormal(__x); } 1406 | constexpr bool 1407 | isnormal(long double __x) 1408 | { return __builtin_isnormal(__x); } 1409 | template 1410 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1411 | bool>::__type 1412 | isnormal(_Tp __x) 1413 | { return __x != 0 ? true : false; } 1414 | constexpr bool 1415 | signbit(float __x) 1416 | { return __builtin_signbit(__x); } 1417 | constexpr bool 1418 | signbit(double __x) 1419 | { return __builtin_signbit(__x); } 1420 | constexpr bool 1421 | signbit(long double __x) 1422 | { return __builtin_signbit(__x); } 1423 | template 1424 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1425 | bool>::__type 1426 | signbit(_Tp __x) 1427 | { return __x < 0 ? true : false; } 1428 | constexpr bool 1429 | isgreater(float __x, float __y) 1430 | { return __builtin_isgreater(__x, __y); } 1431 | constexpr bool 1432 | isgreater(double __x, double __y) 1433 | { return __builtin_isgreater(__x, __y); } 1434 | constexpr bool 1435 | isgreater(long double __x, long double __y) 1436 | { return __builtin_isgreater(__x, __y); } 1437 | template 1438 | constexpr typename 1439 | __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value 1440 | && __is_arithmetic<_Up>::__value), bool>::__type 1441 | isgreater(_Tp __x, _Up __y) 1442 | { 1443 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1444 | return __builtin_isgreater(__type(__x), __type(__y)); 1445 | } 1446 | constexpr bool 1447 | isgreaterequal(float __x, float __y) 1448 | { return __builtin_isgreaterequal(__x, __y); } 1449 | constexpr bool 1450 | isgreaterequal(double __x, double __y) 1451 | { return __builtin_isgreaterequal(__x, __y); } 1452 | constexpr bool 1453 | isgreaterequal(long double __x, long double __y) 1454 | { return __builtin_isgreaterequal(__x, __y); } 1455 | template 1456 | constexpr typename 1457 | __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value 1458 | && __is_arithmetic<_Up>::__value), bool>::__type 1459 | isgreaterequal(_Tp __x, _Up __y) 1460 | { 1461 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1462 | return __builtin_isgreaterequal(__type(__x), __type(__y)); 1463 | } 1464 | constexpr bool 1465 | isless(float __x, float __y) 1466 | { return __builtin_isless(__x, __y); } 1467 | constexpr bool 1468 | isless(double __x, double __y) 1469 | { return __builtin_isless(__x, __y); } 1470 | constexpr bool 1471 | isless(long double __x, long double __y) 1472 | { return __builtin_isless(__x, __y); } 1473 | template 1474 | constexpr typename 1475 | __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value 1476 | && __is_arithmetic<_Up>::__value), bool>::__type 1477 | isless(_Tp __x, _Up __y) 1478 | { 1479 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1480 | return __builtin_isless(__type(__x), __type(__y)); 1481 | } 1482 | constexpr bool 1483 | islessequal(float __x, float __y) 1484 | { return __builtin_islessequal(__x, __y); } 1485 | constexpr bool 1486 | islessequal(double __x, double __y) 1487 | { return __builtin_islessequal(__x, __y); } 1488 | constexpr bool 1489 | islessequal(long double __x, long double __y) 1490 | { return __builtin_islessequal(__x, __y); } 1491 | template 1492 | constexpr typename 1493 | __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value 1494 | && __is_arithmetic<_Up>::__value), bool>::__type 1495 | islessequal(_Tp __x, _Up __y) 1496 | { 1497 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1498 | return __builtin_islessequal(__type(__x), __type(__y)); 1499 | } 1500 | constexpr bool 1501 | islessgreater(float __x, float __y) 1502 | { return __builtin_islessgreater(__x, __y); } 1503 | constexpr bool 1504 | islessgreater(double __x, double __y) 1505 | { return __builtin_islessgreater(__x, __y); } 1506 | constexpr bool 1507 | islessgreater(long double __x, long double __y) 1508 | { return __builtin_islessgreater(__x, __y); } 1509 | template 1510 | constexpr typename 1511 | __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value 1512 | && __is_arithmetic<_Up>::__value), bool>::__type 1513 | islessgreater(_Tp __x, _Up __y) 1514 | { 1515 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1516 | return __builtin_islessgreater(__type(__x), __type(__y)); 1517 | } 1518 | constexpr bool 1519 | isunordered(float __x, float __y) 1520 | { return __builtin_isunordered(__x, __y); } 1521 | constexpr bool 1522 | isunordered(double __x, double __y) 1523 | { return __builtin_isunordered(__x, __y); } 1524 | constexpr bool 1525 | isunordered(long double __x, long double __y) 1526 | { return __builtin_isunordered(__x, __y); } 1527 | template 1528 | constexpr typename 1529 | __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value 1530 | && __is_arithmetic<_Up>::__value), bool>::__type 1531 | isunordered(_Tp __x, _Up __y) 1532 | { 1533 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1534 | return __builtin_isunordered(__type(__x), __type(__y)); 1535 | } 1536 | using ::double_t; 1537 | using ::float_t; 1538 | using ::acosh; 1539 | using ::acoshf; 1540 | using ::acoshl; 1541 | using ::asinh; 1542 | using ::asinhf; 1543 | using ::asinhl; 1544 | using ::atanh; 1545 | using ::atanhf; 1546 | using ::atanhl; 1547 | using ::cbrt; 1548 | using ::cbrtf; 1549 | using ::cbrtl; 1550 | using ::copysign; 1551 | using ::copysignf; 1552 | using ::copysignl; 1553 | using ::erf; 1554 | using ::erff; 1555 | using ::erfl; 1556 | using ::erfc; 1557 | using ::erfcf; 1558 | using ::erfcl; 1559 | using ::exp2; 1560 | using ::exp2f; 1561 | using ::exp2l; 1562 | using ::expm1; 1563 | using ::expm1f; 1564 | using ::expm1l; 1565 | using ::fdim; 1566 | using ::fdimf; 1567 | using ::fdiml; 1568 | using ::fma; 1569 | using ::fmaf; 1570 | using ::fmal; 1571 | using ::fmax; 1572 | using ::fmaxf; 1573 | using ::fmaxl; 1574 | using ::fmin; 1575 | using ::fminf; 1576 | using ::fminl; 1577 | using ::hypot; 1578 | using ::hypotf; 1579 | using ::hypotl; 1580 | using ::ilogb; 1581 | using ::ilogbf; 1582 | using ::ilogbl; 1583 | using ::lgamma; 1584 | using ::lgammaf; 1585 | using ::lgammal; 1586 | using ::llrint; 1587 | using ::llrintf; 1588 | using ::llrintl; 1589 | using ::llround; 1590 | using ::llroundf; 1591 | using ::llroundl; 1592 | using ::log1p; 1593 | using ::log1pf; 1594 | using ::log1pl; 1595 | using ::log2; 1596 | using ::log2f; 1597 | using ::log2l; 1598 | using ::logb; 1599 | using ::logbf; 1600 | using ::logbl; 1601 | using ::lrint; 1602 | using ::lrintf; 1603 | using ::lrintl; 1604 | using ::lround; 1605 | using ::lroundf; 1606 | using ::lroundl; 1607 | using ::nan; 1608 | using ::nanf; 1609 | using ::nanl; 1610 | using ::nearbyint; 1611 | using ::nearbyintf; 1612 | using ::nearbyintl; 1613 | using ::nextafter; 1614 | using ::nextafterf; 1615 | using ::nextafterl; 1616 | using ::nexttoward; 1617 | using ::nexttowardf; 1618 | using ::nexttowardl; 1619 | using ::remainder; 1620 | using ::remainderf; 1621 | using ::remainderl; 1622 | using ::remquo; 1623 | using ::remquof; 1624 | using ::remquol; 1625 | using ::rint; 1626 | using ::rintf; 1627 | using ::rintl; 1628 | using ::round; 1629 | using ::roundf; 1630 | using ::roundl; 1631 | using ::scalbln; 1632 | using ::scalblnf; 1633 | using ::scalblnl; 1634 | using ::scalbn; 1635 | using ::scalbnf; 1636 | using ::scalbnl; 1637 | using ::tgamma; 1638 | using ::tgammaf; 1639 | using ::tgammal; 1640 | using ::trunc; 1641 | using ::truncf; 1642 | using ::truncl; 1643 | constexpr float 1644 | acosh(float __x) 1645 | { return __builtin_acoshf(__x); } 1646 | constexpr long double 1647 | acosh(long double __x) 1648 | { return __builtin_acoshl(__x); } 1649 | template 1650 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1651 | double>::__type 1652 | acosh(_Tp __x) 1653 | { return __builtin_acosh(__x); } 1654 | constexpr float 1655 | asinh(float __x) 1656 | { return __builtin_asinhf(__x); } 1657 | constexpr long double 1658 | asinh(long double __x) 1659 | { return __builtin_asinhl(__x); } 1660 | template 1661 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1662 | double>::__type 1663 | asinh(_Tp __x) 1664 | { return __builtin_asinh(__x); } 1665 | constexpr float 1666 | atanh(float __x) 1667 | { return __builtin_atanhf(__x); } 1668 | constexpr long double 1669 | atanh(long double __x) 1670 | { return __builtin_atanhl(__x); } 1671 | template 1672 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1673 | double>::__type 1674 | atanh(_Tp __x) 1675 | { return __builtin_atanh(__x); } 1676 | constexpr float 1677 | cbrt(float __x) 1678 | { return __builtin_cbrtf(__x); } 1679 | constexpr long double 1680 | cbrt(long double __x) 1681 | { return __builtin_cbrtl(__x); } 1682 | template 1683 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1684 | double>::__type 1685 | cbrt(_Tp __x) 1686 | { return __builtin_cbrt(__x); } 1687 | constexpr float 1688 | copysign(float __x, float __y) 1689 | { return __builtin_copysignf(__x, __y); } 1690 | constexpr long double 1691 | copysign(long double __x, long double __y) 1692 | { return __builtin_copysignl(__x, __y); } 1693 | template 1694 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1695 | copysign(_Tp __x, _Up __y) 1696 | { 1697 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1698 | return copysign(__type(__x), __type(__y)); 1699 | } 1700 | constexpr float 1701 | erf(float __x) 1702 | { return __builtin_erff(__x); } 1703 | constexpr long double 1704 | erf(long double __x) 1705 | { return __builtin_erfl(__x); } 1706 | template 1707 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1708 | double>::__type 1709 | erf(_Tp __x) 1710 | { return __builtin_erf(__x); } 1711 | constexpr float 1712 | erfc(float __x) 1713 | { return __builtin_erfcf(__x); } 1714 | constexpr long double 1715 | erfc(long double __x) 1716 | { return __builtin_erfcl(__x); } 1717 | template 1718 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1719 | double>::__type 1720 | erfc(_Tp __x) 1721 | { return __builtin_erfc(__x); } 1722 | constexpr float 1723 | exp2(float __x) 1724 | { return __builtin_exp2f(__x); } 1725 | constexpr long double 1726 | exp2(long double __x) 1727 | { return __builtin_exp2l(__x); } 1728 | template 1729 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1730 | double>::__type 1731 | exp2(_Tp __x) 1732 | { return __builtin_exp2(__x); } 1733 | constexpr float 1734 | expm1(float __x) 1735 | { return __builtin_expm1f(__x); } 1736 | constexpr long double 1737 | expm1(long double __x) 1738 | { return __builtin_expm1l(__x); } 1739 | template 1740 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1741 | double>::__type 1742 | expm1(_Tp __x) 1743 | { return __builtin_expm1(__x); } 1744 | constexpr float 1745 | fdim(float __x, float __y) 1746 | { return __builtin_fdimf(__x, __y); } 1747 | constexpr long double 1748 | fdim(long double __x, long double __y) 1749 | { return __builtin_fdiml(__x, __y); } 1750 | template 1751 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1752 | fdim(_Tp __x, _Up __y) 1753 | { 1754 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1755 | return fdim(__type(__x), __type(__y)); 1756 | } 1757 | constexpr float 1758 | fma(float __x, float __y, float __z) 1759 | { return __builtin_fmaf(__x, __y, __z); } 1760 | constexpr long double 1761 | fma(long double __x, long double __y, long double __z) 1762 | { return __builtin_fmal(__x, __y, __z); } 1763 | template 1764 | constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type 1765 | fma(_Tp __x, _Up __y, _Vp __z) 1766 | { 1767 | typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; 1768 | return fma(__type(__x), __type(__y), __type(__z)); 1769 | } 1770 | constexpr float 1771 | fmax(float __x, float __y) 1772 | { return __builtin_fmaxf(__x, __y); } 1773 | constexpr long double 1774 | fmax(long double __x, long double __y) 1775 | { return __builtin_fmaxl(__x, __y); } 1776 | template 1777 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1778 | fmax(_Tp __x, _Up __y) 1779 | { 1780 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1781 | return fmax(__type(__x), __type(__y)); 1782 | } 1783 | constexpr float 1784 | fmin(float __x, float __y) 1785 | { return __builtin_fminf(__x, __y); } 1786 | constexpr long double 1787 | fmin(long double __x, long double __y) 1788 | { return __builtin_fminl(__x, __y); } 1789 | template 1790 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1791 | fmin(_Tp __x, _Up __y) 1792 | { 1793 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1794 | return fmin(__type(__x), __type(__y)); 1795 | } 1796 | constexpr float 1797 | hypot(float __x, float __y) 1798 | { return __builtin_hypotf(__x, __y); } 1799 | constexpr long double 1800 | hypot(long double __x, long double __y) 1801 | { return __builtin_hypotl(__x, __y); } 1802 | template 1803 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1804 | hypot(_Tp __x, _Up __y) 1805 | { 1806 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1807 | return hypot(__type(__x), __type(__y)); 1808 | } 1809 | constexpr int 1810 | ilogb(float __x) 1811 | { return __builtin_ilogbf(__x); } 1812 | constexpr int 1813 | ilogb(long double __x) 1814 | { return __builtin_ilogbl(__x); } 1815 | template 1816 | constexpr 1817 | typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1818 | int>::__type 1819 | ilogb(_Tp __x) 1820 | { return __builtin_ilogb(__x); } 1821 | constexpr float 1822 | lgamma(float __x) 1823 | { return __builtin_lgammaf(__x); } 1824 | constexpr long double 1825 | lgamma(long double __x) 1826 | { return __builtin_lgammal(__x); } 1827 | template 1828 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1829 | double>::__type 1830 | lgamma(_Tp __x) 1831 | { return __builtin_lgamma(__x); } 1832 | constexpr long long 1833 | llrint(float __x) 1834 | { return __builtin_llrintf(__x); } 1835 | constexpr long long 1836 | llrint(long double __x) 1837 | { return __builtin_llrintl(__x); } 1838 | template 1839 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1840 | long long>::__type 1841 | llrint(_Tp __x) 1842 | { return __builtin_llrint(__x); } 1843 | constexpr long long 1844 | llround(float __x) 1845 | { return __builtin_llroundf(__x); } 1846 | constexpr long long 1847 | llround(long double __x) 1848 | { return __builtin_llroundl(__x); } 1849 | template 1850 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1851 | long long>::__type 1852 | llround(_Tp __x) 1853 | { return __builtin_llround(__x); } 1854 | constexpr float 1855 | log1p(float __x) 1856 | { return __builtin_log1pf(__x); } 1857 | constexpr long double 1858 | log1p(long double __x) 1859 | { return __builtin_log1pl(__x); } 1860 | template 1861 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1862 | double>::__type 1863 | log1p(_Tp __x) 1864 | { return __builtin_log1p(__x); } 1865 | constexpr float 1866 | log2(float __x) 1867 | { return __builtin_log2f(__x); } 1868 | constexpr long double 1869 | log2(long double __x) 1870 | { return __builtin_log2l(__x); } 1871 | template 1872 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1873 | double>::__type 1874 | log2(_Tp __x) 1875 | { return __builtin_log2(__x); } 1876 | constexpr float 1877 | logb(float __x) 1878 | { return __builtin_logbf(__x); } 1879 | constexpr long double 1880 | logb(long double __x) 1881 | { return __builtin_logbl(__x); } 1882 | template 1883 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1884 | double>::__type 1885 | logb(_Tp __x) 1886 | { return __builtin_logb(__x); } 1887 | constexpr long 1888 | lrint(float __x) 1889 | { return __builtin_lrintf(__x); } 1890 | constexpr long 1891 | lrint(long double __x) 1892 | { return __builtin_lrintl(__x); } 1893 | template 1894 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1895 | long>::__type 1896 | lrint(_Tp __x) 1897 | { return __builtin_lrint(__x); } 1898 | constexpr long 1899 | lround(float __x) 1900 | { return __builtin_lroundf(__x); } 1901 | constexpr long 1902 | lround(long double __x) 1903 | { return __builtin_lroundl(__x); } 1904 | template 1905 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1906 | long>::__type 1907 | lround(_Tp __x) 1908 | { return __builtin_lround(__x); } 1909 | constexpr float 1910 | nearbyint(float __x) 1911 | { return __builtin_nearbyintf(__x); } 1912 | constexpr long double 1913 | nearbyint(long double __x) 1914 | { return __builtin_nearbyintl(__x); } 1915 | template 1916 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1917 | double>::__type 1918 | nearbyint(_Tp __x) 1919 | { return __builtin_nearbyint(__x); } 1920 | constexpr float 1921 | nextafter(float __x, float __y) 1922 | { return __builtin_nextafterf(__x, __y); } 1923 | constexpr long double 1924 | nextafter(long double __x, long double __y) 1925 | { return __builtin_nextafterl(__x, __y); } 1926 | template 1927 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1928 | nextafter(_Tp __x, _Up __y) 1929 | { 1930 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1931 | return nextafter(__type(__x), __type(__y)); 1932 | } 1933 | constexpr float 1934 | nexttoward(float __x, long double __y) 1935 | { return __builtin_nexttowardf(__x, __y); } 1936 | constexpr long double 1937 | nexttoward(long double __x, long double __y) 1938 | { return __builtin_nexttowardl(__x, __y); } 1939 | template 1940 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1941 | double>::__type 1942 | nexttoward(_Tp __x, long double __y) 1943 | { return __builtin_nexttoward(__x, __y); } 1944 | constexpr float 1945 | remainder(float __x, float __y) 1946 | { return __builtin_remainderf(__x, __y); } 1947 | constexpr long double 1948 | remainder(long double __x, long double __y) 1949 | { return __builtin_remainderl(__x, __y); } 1950 | template 1951 | constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1952 | remainder(_Tp __x, _Up __y) 1953 | { 1954 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1955 | return remainder(__type(__x), __type(__y)); 1956 | } 1957 | inline float 1958 | remquo(float __x, float __y, int* __pquo) 1959 | { return __builtin_remquof(__x, __y, __pquo); } 1960 | inline long double 1961 | remquo(long double __x, long double __y, int* __pquo) 1962 | { return __builtin_remquol(__x, __y, __pquo); } 1963 | template 1964 | inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type 1965 | remquo(_Tp __x, _Up __y, int* __pquo) 1966 | { 1967 | typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; 1968 | return remquo(__type(__x), __type(__y), __pquo); 1969 | } 1970 | constexpr float 1971 | rint(float __x) 1972 | { return __builtin_rintf(__x); } 1973 | constexpr long double 1974 | rint(long double __x) 1975 | { return __builtin_rintl(__x); } 1976 | template 1977 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1978 | double>::__type 1979 | rint(_Tp __x) 1980 | { return __builtin_rint(__x); } 1981 | constexpr float 1982 | round(float __x) 1983 | { return __builtin_roundf(__x); } 1984 | constexpr long double 1985 | round(long double __x) 1986 | { return __builtin_roundl(__x); } 1987 | template 1988 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 1989 | double>::__type 1990 | round(_Tp __x) 1991 | { return __builtin_round(__x); } 1992 | constexpr float 1993 | scalbln(float __x, long __ex) 1994 | { return __builtin_scalblnf(__x, __ex); } 1995 | constexpr long double 1996 | scalbln(long double __x, long __ex) 1997 | { return __builtin_scalblnl(__x, __ex); } 1998 | template 1999 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 2000 | double>::__type 2001 | scalbln(_Tp __x, long __ex) 2002 | { return __builtin_scalbln(__x, __ex); } 2003 | constexpr float 2004 | scalbn(float __x, int __ex) 2005 | { return __builtin_scalbnf(__x, __ex); } 2006 | constexpr long double 2007 | scalbn(long double __x, int __ex) 2008 | { return __builtin_scalbnl(__x, __ex); } 2009 | template 2010 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 2011 | double>::__type 2012 | scalbn(_Tp __x, int __ex) 2013 | { return __builtin_scalbn(__x, __ex); } 2014 | constexpr float 2015 | tgamma(float __x) 2016 | { return __builtin_tgammaf(__x); } 2017 | constexpr long double 2018 | tgamma(long double __x) 2019 | { return __builtin_tgammal(__x); } 2020 | template 2021 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 2022 | double>::__type 2023 | tgamma(_Tp __x) 2024 | { return __builtin_tgamma(__x); } 2025 | constexpr float 2026 | trunc(float __x) 2027 | { return __builtin_truncf(__x); } 2028 | constexpr long double 2029 | trunc(long double __x) 2030 | { return __builtin_truncl(__x); } 2031 | template 2032 | constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 2033 | double>::__type 2034 | trunc(_Tp __x) 2035 | { return __builtin_trunc(__x); } 2036 | } 2037 | } 2038 | using std::abs; 2039 | using std::acos; 2040 | using std::asin; 2041 | using std::atan; 2042 | using std::atan2; 2043 | using std::cos; 2044 | using std::sin; 2045 | using std::tan; 2046 | using std::cosh; 2047 | using std::sinh; 2048 | using std::tanh; 2049 | using std::exp; 2050 | using std::frexp; 2051 | using std::ldexp; 2052 | using std::log; 2053 | using std::log10; 2054 | using std::modf; 2055 | using std::pow; 2056 | using std::sqrt; 2057 | using std::ceil; 2058 | using std::fabs; 2059 | using std::floor; 2060 | using std::fmod; 2061 | using std::fpclassify; 2062 | using std::isfinite; 2063 | using std::isinf; 2064 | using std::isnan; 2065 | using std::isnormal; 2066 | using std::signbit; 2067 | using std::isgreater; 2068 | using std::isgreaterequal; 2069 | using std::isless; 2070 | using std::islessequal; 2071 | using std::islessgreater; 2072 | using std::isunordered; 2073 | using std::acosh; 2074 | using std::asinh; 2075 | using std::atanh; 2076 | using std::cbrt; 2077 | using std::copysign; 2078 | using std::erf; 2079 | using std::erfc; 2080 | using std::exp2; 2081 | using std::expm1; 2082 | using std::fdim; 2083 | using std::fma; 2084 | using std::fmax; 2085 | using std::fmin; 2086 | using std::hypot; 2087 | using std::ilogb; 2088 | using std::lgamma; 2089 | using std::llrint; 2090 | using std::llround; 2091 | using std::log1p; 2092 | using std::log2; 2093 | using std::logb; 2094 | using std::lrint; 2095 | using std::lround; 2096 | using std::nearbyint; 2097 | using std::nextafter; 2098 | using std::nexttoward; 2099 | using std::remainder; 2100 | using std::remquo; 2101 | using std::rint; 2102 | using std::round; 2103 | using std::scalbln; 2104 | using std::scalbn; 2105 | using std::tgamma; 2106 | using std::trunc; 2107 | `; 2108 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | exports.SUPPORTED_BOARDS = { 2 | "ESPRUINOBOARD":{cpu:"cortexm3"}, 3 | "PICO_R1_3":{cpu:"cortexm4"}, 4 | "ESPRUINOWIFI":{cpu:"cortexm4"}, 5 | "BANGLEJS":{cpu:"cortexm4", nrf52:true}, 6 | "BANGLEJS2":{cpu:"cortexm4", nrf52:true}, 7 | "PUCKJS":{cpu:"cortexm4", nrf52:true}, 8 | "PIXLJS":{cpu:"cortexm4", nrf52:true}, 9 | "JOLTJS":{cpu:"cortexm4", nrf52:true}, 10 | "MDBT42Q":{cpu:"cortexm4", nrf52:true}, 11 | "MINEWI10":{cpu:"cortexm4", nrf52:true}, 12 | "NRF52832DK":{cpu:"cortexm4",nrf52:true}, 13 | "NRF52840DK":{cpu:"cortexm4",nrf52:true}, 14 | "DICKENS":{cpu:"cortexm4",nrf52:true}, 15 | "PIPBOY":{cpu:"cortexm4"}, 16 | }; 17 | 18 | exports.isFloat = function(n) { 19 | return (typeof n == "number") && 20 | (n === +n && n !== (n|0)); 21 | }; 22 | 23 | exports.isInt = function(n) { 24 | return (typeof n == "number") && 25 | !(n === +n && n !== (n|0)); 26 | }; 27 | 28 | exports.isBool = function(n) { 29 | return typeof n == "boolean"; 30 | }; 31 | 32 | // Give two types, find the 'maximum' type 33 | exports.maxType = function(a,b) { 34 | var typeOrder = ["bool","int","JsVar" ]; 35 | var ai = typeOrder.indexOf(a); 36 | var bi = typeOrder.indexOf(b); 37 | if (ai<0 || bi<0) return undefined; 38 | return typeOrder[Math.max(ai,bi)]; 39 | }; 40 | 41 | exports.getMathsOpOperator = function(op) { 42 | if (op.length==1) return "'"+op+"'"; 43 | // see jsutils.h 44 | if (op=="==") return 138; // LEX_EQUAL 45 | if (op=="===") return 139; // LEX_TYPEEQUALL 46 | if (op=="!=") return 140; // LEX_NEQUAL 47 | if (op=="!==") return 141; // LEX_NTYPEEQUAL 48 | if (op=="<=") return 142; // LEX_LEQUAL 49 | if (op=="<<") return 143; // LEX_LSHIFT 50 | // LEX_LSHIFTEQUAL 51 | if (op==">=") return 145; //LEX_GEQUAL 52 | if (op==">>") return 146; // LEX_RSHIFT 53 | if (op==">>>") return 147; // LEX_RSHIFTUNSIGNED 54 | // LEX_RSHIFTEQUAL 55 | // LEX_RSHIFTUNSIGNEDEQUAL 56 | // LEX_PLUSEQUAL 57 | // LEX_MINUSEQUAL 58 | // LEX_PLUSPLUS 59 | // LEX_MINUSMINUS 60 | // LEX_MULEQUAL 61 | // LEX_DIVEQUAL 62 | // LEX_MODEQUAL 63 | // LEX_ANDEQUAL 64 | if (op=="&&") return 158; // LEX_ANDAND 65 | // LEX_OREQUAL 66 | if (op=="||") return 160; // LEX_OROR 67 | // LEX_XOREQUAL 68 | throw new Error("Unknown op '"+op+"'"); 69 | }; 70 | 71 | exports.getFunctionDecls = function(exports) { 72 | var code = "class JsVar;\n"; 73 | // the order of these must match jswrap_process.c 74 | var funcDecls = { 75 | "jsvLockAgainSafe" : "JsVar *(*jsvLockAgainSafe)(JsVar *v) = (JsVar *(*)(JsVar *))", 76 | "jsvUnLock" : "void (*jsvUnLock)(JsVar *v) = (void(*)(JsVar *))", 77 | "jsvSkipName" : "JsVar *(*jsvSkipName)(JsVar *a) = (JsVar *(*)(JsVar *))", 78 | "jsvMathsOp" : "JsVar *(*jsvMathsOp)(JsVar *a, JsVar *b, int op) = (JsVar *(*)(JsVar *,JsVar*,int))", 79 | "jsvNewWithFlags" : "JsVar *(*jsvNewWithFlags)(int flags) = (JsVar *(*)(int))", 80 | "jsvNewFromFloat" : "JsVar *(*jsvNewFromFloat)(double d) = (JsVar *(*)(double))", 81 | "jsvNewFromInteger" : "JsVar *(*jsvNewFromInteger)(int i) = (JsVar *(*)(int))", 82 | "jsvNewFromString" : "JsVar *(*jsvNewFromString)(const char *s) = (JsVar *(*)(const char *))", 83 | "jsvNewFromBool" : "JsVar *(*jsvNewFromBool)(bool b) = (JsVar *(*)(bool))", 84 | "jsvGetFloat" : "double (*jsvGetFloat)(JsVar *v) = (double(*)(JsVar *))", 85 | "jsvGetInteger" : "int (*jsvGetInteger)(JsVar *v) = (int(*)(JsVar *))", 86 | "jsvGetBool" : "bool (*jsvGetBool)(JsVar *v) = (bool(*)(JsVar *))", 87 | "jsvReplaceWith" : "void (*jsvReplaceWith)(JsVar *a, JsVar *b) = (void(*)(JsVar *, JsVar *))", 88 | "jspeFunctionCall" : "JsVar *(*jspeFunctionCall)(JsVar *function, JsVar *functionName, JsVar *thisArg, bool isParsing, int argCount, JsVar **argPtr) = (JsVar *(*)(JsVar *, JsVar *, JsVar *, bool, int, JsVar **))", 89 | "jspGetNamedVariable" : "JsVar *(*jspGetNamedVariable)(const char *n) = (JsVar *(*)(const char *))", 90 | "jspGetNamedField" : "JsVar *(*jspGetNamedField)(JsVar *o, const char *n, bool returnName) = (JsVar *(*)(JsVar *,const char *, bool))", 91 | "jspGetVarNamedField" : "JsVar *(*jspGetVarNamedField)(JsVar *object, JsVar *nameVar, bool returnName) = (JsVar *(*)(JsVar *,JsVar *, bool))", 92 | }; 93 | 94 | if ("number"==typeof exports) { 95 | code += "const void **EXPTR = (const void**)"+exports+";\n"; 96 | // we should probably do this automatically, but lets just write it out 97 | code += ` 98 | JsVar * jsvLockAgainSafe(JsVar *v) { 99 | return ( (JsVar *(*)(JsVar *))EXPTR[0])(v); 100 | } 101 | void jsvUnLock(JsVar *v) { 102 | return ( (void(*)(JsVar *))EXPTR[1])(v); 103 | } 104 | JsVar * jsvSkipName(JsVar *a) { 105 | return ( (JsVar *(*)(JsVar *))EXPTR[2])(a); 106 | } 107 | JsVar * jsvMathsOp(JsVar *a, JsVar *b, int op) { 108 | return ( (JsVar *(*)(JsVar *,JsVar*,int))EXPTR[3])(a,b,op); 109 | } 110 | JsVar * jsvNewWithFlags(int flags) { 111 | return ( (JsVar *(*)(int))EXPTR[4])(flags); 112 | } 113 | JsVar * jsvNewFromFloat(double d) { 114 | return ( (JsVar *(*)(double))EXPTR[5])(d); 115 | } 116 | JsVar * jsvNewFromInteger(int i) { 117 | return ( (JsVar *(*)(int))EXPTR[6])(i); 118 | } 119 | JsVar * jsvNewFromString(const char *s) { 120 | return ( (JsVar *(*)(const char *))EXPTR[7])(s); 121 | } 122 | JsVar * jsvNewFromBool(bool b) { 123 | return ( (JsVar *(*)(bool))EXPTR[8])(b); 124 | } 125 | double jsvGetFloat(JsVar *v) { 126 | return ( (double(*)(JsVar *))EXPTR[9])(v); 127 | } 128 | int jsvGetInteger(JsVar *v) { 129 | return ( (int(*)(JsVar *))EXPTR[10])(v); 130 | } 131 | bool jsvGetBool(JsVar *v) { 132 | return ( (bool(*)(JsVar *))EXPTR[11])(v); 133 | } 134 | void jsvReplaceWith(JsVar *a, JsVar *b) { 135 | return ( (void(*)(JsVar *, JsVar *))EXPTR[12])(a,b); 136 | } 137 | JsVar * jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *thisArg, bool isParsing, int argCount, JsVar **argPtr) { 138 | return ( (JsVar *(*)(JsVar *, JsVar *, JsVar *, bool, int, JsVar **))EXPTR[13])(function,functionName,thisArg,isParsing,argCount,argPtr); 139 | } 140 | JsVar * jspGetNamedVariable(const char *n) { 141 | return ( (JsVar *(*)(const char *))EXPTR[14])(n); 142 | } 143 | JsVar * jspGetNamedField(JsVar *o, const char *n, bool returnName) { 144 | return ( (JsVar *(*)(JsVar *,const char *, bool))EXPTR[15])(o,n,returnName); 145 | } 146 | JsVar * jspGetVarNamedField(JsVar *object, JsVar *nameVar, bool returnName) { 147 | return ( (JsVar *(*)(JsVar *,JsVar *, bool))EXPTR[16])(object,nameVar,returnName); 148 | } 149 | 150 | `; 151 | /*var n = 0; // this mostly generates the above, apart from arg names 152 | for (var name in funcDecls) { 153 | var decl = funcDecls[name]; 154 | var match = decl.match(/(.*)\(\*\w*\)(.*)=(.*)/); 155 | code += match[1]+" "+name+match[2]+"{\n"; 156 | code += " return ("+match[3]+"EXPTR["+n+"])();\n"; 157 | code += "}\n"; 158 | n++; 159 | }*/ 160 | return code; 161 | } 162 | 163 | 164 | for (var f in funcDecls) { 165 | if (!f in exports) throw new Error("Function '"+f+"' not found in exports list!"); 166 | //var addr = baseAddr + idx*4; addr = "*(unsigned int*)"+addr; 167 | var addr = exports[f]; 168 | code += funcDecls[f]+addr+";\n"; 169 | } 170 | return code; 171 | }; 172 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var acorn = require("acorn"); 2 | compileFunction = require("./src/compile.js").compileFunction; 3 | 4 | var exports = { "jsvLock": 14545, "jsvLockAgainSafe": 14533, "jsvUnLock": 14509, "jsvSkipName": 43285, 5 | "jsvMathsOp": 82821, "jsvMathsOpSkipNames": 163963, "jsvNewFromFloat": 174517, "jsvNewFromInteger": 174559, "jsvNewFromString": 174989, 6 | "jsvNewFromBool": 174537, "jsvGetFloat": 76897, "jsvGetInteger": 173429, "jsvGetBool": 77173, "jspeiFindInScopes": 37173, 7 | "jsvReplaceWith": 96345, "jspeFunctionCall": 127017, "jspGetNamedVariable": 93377, "jspGetNamedField": 93233, "jspGetVarNamedField": 92833, 8 | "jsvNewWithFlags": 174313 }; 9 | var options = {exports:exports, boardInfo:{cpu:"cortexm4"}}; 10 | 11 | function compileCode(code, callback) { 12 | var offset = 0; 13 | var tasks = 0; 14 | try { 15 | var ast = acorn.parse(code, { ecmaVersion : 6 }); 16 | ast.body.forEach(function(node) { 17 | if (node.type=="FunctionDeclaration") { 18 | if (node.body.type=="BlockStatement" && 19 | node.body.body.length>0 && 20 | node.body.body[0].type=="ExpressionStatement" && 21 | node.body.body[0].expression.type=="Literal" && 22 | node.body.body[0].expression.value=="compiled") { 23 | try { 24 | tasks++; 25 | compileFunction(node, options, function(newCode) { 26 | if (newCode) { 27 | //console.log(asm); 28 | //console.log(node); 29 | code = code.substr(0,node.start+offset) + newCode + code.substr(node.end+offset); 30 | offset += newCode.length - (node.end-node.start); // offset for future code snippets 31 | } 32 | tasks--; 33 | if (tasks==0) 34 | callback(code); 35 | }); 36 | } catch (err) { 37 | console.warn(err.stack); 38 | console.warn("In 'compiled' function: "+err.toString()); 39 | } 40 | 41 | /**/ 42 | } 43 | } 44 | }); 45 | } catch (err) { 46 | console.log(err); 47 | console.warn("Acorn parse for plugins/compiler.js failed. Your code is probably broken."); 48 | callback(); 49 | } 50 | if (tasks==0) 51 | callback(code); 52 | } 53 | 54 | 55 | compileCode(require("fs").readFileSync("tests/test.js").toString(), function(d) { 56 | console.log("========================================================== FINAL:"); 57 | console.log(d); 58 | }); 59 | -------------------------------------------------------------------------------- /test_espruino.js: -------------------------------------------------------------------------------- 1 | // Test by compiling the code into Espruino itself 2 | var acorn = require("acorn"); 3 | var fs = require("fs"); 4 | var jsToC = require("./src/compile.js").jsToC; 5 | 6 | var filename = "tests/test.js"; 7 | 8 | var js = fs.readFileSync(filename).toString(); 9 | var ast = acorn.parse(js, { ecmaVersion : 6 }); 10 | ast.body.forEach(function(node) { 11 | if (node.type=="FunctionDeclaration") { 12 | if (node.body.type=="BlockStatement" && 13 | node.body.body.length>0 && 14 | node.body.body[0].type=="ExpressionStatement" && 15 | node.body.body[0].expression.type=="Literal" && 16 | node.body.body[0].expression.value=="compiled") { 17 | 18 | var compiled = jsToC(node); 19 | 20 | fs.writeFileSync(filename+".h", compiled.cArgSpec+";\n"); 21 | fs.writeFileSync(filename+".c", 22 | '/*JSON{\n'+ 23 | ' "type" : "function",\n'+ 24 | ' "name" : "'+compiled.functionName+'",\n'+ 25 | ' "generate" : "'+compiled.functionName+'",\n'+ 26 | ' "params" : [\n'+ 27 | ' ["a","JsVar",""],\n'+ 28 | ' ["b","JsVar",""],\n'+ 29 | ' ["c","JsVar",""]\n'+ 30 | ' ],\n'+ 31 | ' "return" : ["JsVar",""]\n'+ 32 | '}\n'+ 33 | '*/\n'); 34 | fs.writeFileSync(filename+"c.cpp", 35 | 'extern "C" {\n'+ 36 | '#include "src/jsvar.h"\n'+ 37 | '#include "src/jsparse.h"\n'+ 38 | "#include "+JSON.stringify("../"+filename+".h")+"\n"+ 39 | "}\n"+ 40 | "\n"+ 41 | compiled.code+"\n"); 42 | 43 | var exec = require('child_process').exec; 44 | var cmd = "DEBUG=1 CFILE=../EspruinoCompiler/"+filename+".c CPPFILE=../EspruinoCompiler/"+filename+"c.cpp make"; 45 | exec(cmd, { cwd : "../Espruino" }, function (error, stdout, stderr) { 46 | if (stdout) console.log('stdout: ' + stdout+"\n"); 47 | if (stderr) console.log('stderr: ' + stderr+"\n"); 48 | }); 49 | } 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | // Start 2 | function fa() { 3 | "compiled"; 4 | var x = 1; 5 | for (var i=0;i<8;i++) { 6 | x = x * 1.5; 7 | } 8 | return x; 9 | } 10 | 11 | function fb() { 12 | "compiled"; 13 | for (var y=0;y<32;y++) { 14 | line=""; 15 | for (var x=0;x<32;x++) { 16 | var Xr=0; 17 | var Xi=0; 18 | var Cr=(4.0*x/32)-2.0; 19 | var Ci=(4.0*y/32)-2.0; 20 | var i=0; 21 | while ((i<8) && ((Xr*Xr+Xi*Xi)<4)) { 22 | var t=Xr*Xr - Xi*Xi + Cr; 23 | Xi=2*Xr*Xi+Ci; 24 | Xr=t; 25 | i++; 26 | } 27 | if (i&1) 28 | line += "*"; 29 | else 30 | line += " "; 31 | } 32 | print(line); 33 | } 34 | } 35 | 36 | function fc(a,b,c) { 37 | "compiled"; 38 | var i=""; 39 | i+=a; 40 | i+=b; 41 | i+=c; 42 | return i; 43 | } 44 | 45 | 46 | // End 47 | -------------------------------------------------------------------------------- /tmp/README.md: -------------------------------------------------------------------------------- 1 | Temporary files created by compiler/GCC 2 | --------------------------------------------------------------------------------