TinyJS on mbed. TinyJS is very simple JavaScript engine.

Dependencies:   mbed

TinyJS on mbed

what's this ?

TinyJS is an extremely simple (under than 2000 lines) JavaScript interpreter engine.
I ported on mbed. but it restrict any features.
TinyJS project is https://github.com/gfwilliams/tiny-js

TinyJSは2000行以下で書かれた非常に小さいJavaScriptインタプリタエンジンです。
これをmbedに移植してみました。(ただし、いろいろ制限があります)
本家はこちら。 https://github.com/gfwilliams/tiny-js

how to use

You must use on serial terminal application by mbed serial USB.
baud is 57600bps
USBシリアルとして、ターミナルソフトを接続するとコンソールが表示されます。
ボーレートは57600bpsになってます。

functions

functions for mbed.
mbed用関数

  • mbed.DigitalIn(pinName, mode)
  • mbed.DigitalOut(pinName, val)
  • mbed.AnalogIn(pinName)
  • mbed.AnalogOut(pinName, val)
  • mbed.InterruptIn(pinName, edge, mode, callback)
  • mbed.TimerStart()
  • mbed.TimerStop()
  • mbed.TimerReset()
  • mbed.TimerRead()
  • mbed.Timeout(callback, t)
  • mbed.wait(s)
  • mbed.memfree()

sample JavaScript codes

DigitalOut

mbed.DigitalOut('LED1', 1);
mbed.DigitalOut('LED2', 0);
mbed.DigitalOut('LED3', 1);
mbed.DigitalOut('LED4', 0);

LED1 = On, LED2=Off, LED3=On, ED4=Off
LED1 = 点灯、LED2=消灯、LED3=点灯、LED4=消灯

DigitalIn

print(mbed.DigitalIn('p5', 'PullUp'));

p5 is pull up, read, and print on console.
p5をPullUpして読みプリントする。

AnalogOut

mbed.AnalogOut('p18', 0.8);

p18 is analog output, value is 0.8.
p18を 値0.8でアナログ出力する。

AnalogIn

print(mbed.AnalogIn('p20'));

p20 is read analog voltage, and print on console.
p20をアナログ入力しプリントする。

InterruptIn

var led1 = 0;
mbed.InterruptIn('p5', 'fall', 'PullUp', function() {led1 = !led1; mbed.DigitalOut('LED1', led1);});

Interrupt on p5, and ON/OFF does LED1.
p5で割り込んでLED1をON/OFFする。

Timeout and wait sample code

mbed.Timeout(function() {mbed.DigitalOut('LED1', 1);mbed.wait(3);mbed.DigitalOut('LED1', 0);}, 4);

LED1=on when wait for 4 seconds. and LED1=off for 3 seconds later.
LED1を4秒待って点灯して3秒後に消灯する。

memfree

print(mbed.memfree());

This prints the number of bytes of the remainder memory on mbed where TinyJS is usable.
これはTinyJSが使えるmbed上での残りメモリのバイト数をプリントアウトする。

LED Blinker by Timeout

blinker = function() {var led = 0; mbed.Timeout(function() {led = !led; mbed.DigitalOut('LED1', led);blinker();}, 0.5);};
blinker();

LED Blinker by Timeout.
Timeoutを使ったLチカ。

restrictions

  • There is very little available memory. (Less than 9kbytes on LPC1768)
  • Registration of InterruptIn is 4 limit.
  • The loop to 8,192 times.
  • The built-in functions (general JavaScript functions) that TinyJS prepares for for securing of memory is not included.

more, more, more ....

制限事項

  • 利用できるメモリは非常に少ない。(LPC1768で9kbytes以下)
  • InterruptInで登録できる割り込みは4つまで。4つを超えると1つめから順番に削除される。
  • ループは8192回まで。
  • メモリ確保のためTinyJSが用意している組み込み関数(一般的なJavaScript関数)は含まれない。

他、多数....

sample movies

http://www.youtube.com/watch?v=ARp0DK70JGM
http://www.youtube.com/watch?v=UOZQ4eEC4xA

Committer:
ohneta
Date:
Mon Jan 20 00:07:35 2014 +0000
Revision:
8:819934a27c2d
Parent:
0:aae260bdcdd9
update InterruptIn, Timer, Timeout functons

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ohneta 0:aae260bdcdd9 1 /*
ohneta 0:aae260bdcdd9 2 * TinyJS
ohneta 0:aae260bdcdd9 3 *
ohneta 0:aae260bdcdd9 4 * A single-file Javascript-alike engine
ohneta 0:aae260bdcdd9 5 *
ohneta 0:aae260bdcdd9 6 * Authored By Gordon Williams <gw@pur3.co.uk>
ohneta 0:aae260bdcdd9 7 *
ohneta 0:aae260bdcdd9 8 * Copyright (C) 2009 Pur3 Ltd
ohneta 0:aae260bdcdd9 9 *
ohneta 0:aae260bdcdd9 10 * Permission is hereby granted, free of charge, to any person obtaining a copy of
ohneta 0:aae260bdcdd9 11 * this software and associated documentation files (the "Software"), to deal in
ohneta 0:aae260bdcdd9 12 * the Software without restriction, including without limitation the rights to
ohneta 0:aae260bdcdd9 13 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
ohneta 0:aae260bdcdd9 14 * of the Software, and to permit persons to whom the Software is furnished to do
ohneta 0:aae260bdcdd9 15 * so, subject to the following conditions:
ohneta 0:aae260bdcdd9 16
ohneta 0:aae260bdcdd9 17 * The above copyright notice and this permission notice shall be included in all
ohneta 0:aae260bdcdd9 18 * copies or substantial portions of the Software.
ohneta 0:aae260bdcdd9 19
ohneta 0:aae260bdcdd9 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
ohneta 0:aae260bdcdd9 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
ohneta 0:aae260bdcdd9 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
ohneta 0:aae260bdcdd9 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
ohneta 0:aae260bdcdd9 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ohneta 0:aae260bdcdd9 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ohneta 0:aae260bdcdd9 26 * SOFTWARE.
ohneta 0:aae260bdcdd9 27 */
ohneta 0:aae260bdcdd9 28 /*
ohneta 0:aae260bdcdd9 29 * TinyJS for mbed.
ohneta 0:aae260bdcdd9 30 *
ohneta 0:aae260bdcdd9 31 * Authored by Takehisa Oneta (ohneta@gmail.com)
ohneta 0:aae260bdcdd9 32 * 10th Jan. 2013
ohneta 0:aae260bdcdd9 33 */
ohneta 0:aae260bdcdd9 34
ohneta 0:aae260bdcdd9 35 #ifndef TINYJS_H
ohneta 0:aae260bdcdd9 36 #define TINYJS_H
ohneta 0:aae260bdcdd9 37
ohneta 0:aae260bdcdd9 38 // If defined, this keeps a note of all calls and where from in memory. This is slower, but good for debugging
ohneta 0:aae260bdcdd9 39 #define TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 40
ohneta 0:aae260bdcdd9 41 #ifdef _WIN32
ohneta 0:aae260bdcdd9 42 #ifdef _DEBUG
ohneta 0:aae260bdcdd9 43 #define _CRTDBG_MAP_ALLOC
ohneta 0:aae260bdcdd9 44 #include <stdlib.h>
ohneta 0:aae260bdcdd9 45 #include <crtdbg.h>
ohneta 0:aae260bdcdd9 46 #endif
ohneta 0:aae260bdcdd9 47 #endif
ohneta 0:aae260bdcdd9 48 #include <string>
ohneta 0:aae260bdcdd9 49 #include <vector>
ohneta 0:aae260bdcdd9 50
ohneta 0:aae260bdcdd9 51 #ifndef TRACE
ohneta 0:aae260bdcdd9 52 #define TRACE printf
ohneta 0:aae260bdcdd9 53 #endif // TRACE
ohneta 0:aae260bdcdd9 54
ohneta 0:aae260bdcdd9 55 #ifndef MBED
ohneta 0:aae260bdcdd9 56 #define MBED 1
ohneta 0:aae260bdcdd9 57 #endif // MBED
ohneta 0:aae260bdcdd9 58
ohneta 0:aae260bdcdd9 59 #define DEBUG_MEMORY 0
ohneta 0:aae260bdcdd9 60
ohneta 0:aae260bdcdd9 61
ohneta 0:aae260bdcdd9 62 const int TINYJS_LOOP_MAX_ITERATIONS = 8192;
ohneta 0:aae260bdcdd9 63
ohneta 0:aae260bdcdd9 64 enum LEX_TYPES {
ohneta 0:aae260bdcdd9 65 LEX_EOF = 0,
ohneta 0:aae260bdcdd9 66 LEX_ID = 256,
ohneta 0:aae260bdcdd9 67 LEX_INT,
ohneta 0:aae260bdcdd9 68 LEX_FLOAT,
ohneta 0:aae260bdcdd9 69 LEX_STR,
ohneta 0:aae260bdcdd9 70
ohneta 0:aae260bdcdd9 71 LEX_EQUAL,
ohneta 0:aae260bdcdd9 72 LEX_TYPEEQUAL,
ohneta 0:aae260bdcdd9 73 LEX_NEQUAL,
ohneta 0:aae260bdcdd9 74 LEX_NTYPEEQUAL,
ohneta 0:aae260bdcdd9 75 LEX_LEQUAL,
ohneta 0:aae260bdcdd9 76 LEX_LSHIFT,
ohneta 0:aae260bdcdd9 77 LEX_LSHIFTEQUAL,
ohneta 0:aae260bdcdd9 78 LEX_GEQUAL,
ohneta 0:aae260bdcdd9 79 LEX_RSHIFT,
ohneta 0:aae260bdcdd9 80 LEX_RSHIFTUNSIGNED,
ohneta 0:aae260bdcdd9 81 LEX_RSHIFTEQUAL,
ohneta 0:aae260bdcdd9 82 LEX_PLUSEQUAL,
ohneta 0:aae260bdcdd9 83 LEX_MINUSEQUAL,
ohneta 0:aae260bdcdd9 84 LEX_PLUSPLUS,
ohneta 0:aae260bdcdd9 85 LEX_MINUSMINUS,
ohneta 0:aae260bdcdd9 86 LEX_ANDEQUAL,
ohneta 0:aae260bdcdd9 87 LEX_ANDAND,
ohneta 0:aae260bdcdd9 88 LEX_OREQUAL,
ohneta 0:aae260bdcdd9 89 LEX_OROR,
ohneta 0:aae260bdcdd9 90 LEX_XOREQUAL,
ohneta 0:aae260bdcdd9 91 // reserved words
ohneta 0:aae260bdcdd9 92 #define LEX_R_LIST_START LEX_R_IF
ohneta 0:aae260bdcdd9 93 LEX_R_IF,
ohneta 0:aae260bdcdd9 94 LEX_R_ELSE,
ohneta 0:aae260bdcdd9 95 LEX_R_DO,
ohneta 0:aae260bdcdd9 96 LEX_R_WHILE,
ohneta 0:aae260bdcdd9 97 LEX_R_FOR,
ohneta 0:aae260bdcdd9 98 LEX_R_BREAK,
ohneta 0:aae260bdcdd9 99 LEX_R_CONTINUE,
ohneta 0:aae260bdcdd9 100 LEX_R_FUNCTION,
ohneta 0:aae260bdcdd9 101 LEX_R_RETURN,
ohneta 0:aae260bdcdd9 102 LEX_R_VAR,
ohneta 0:aae260bdcdd9 103 LEX_R_TRUE,
ohneta 0:aae260bdcdd9 104 LEX_R_FALSE,
ohneta 0:aae260bdcdd9 105 LEX_R_NULL,
ohneta 0:aae260bdcdd9 106 LEX_R_UNDEFINED,
ohneta 0:aae260bdcdd9 107 LEX_R_NEW,
ohneta 0:aae260bdcdd9 108
ohneta 0:aae260bdcdd9 109 LEX_R_LIST_END /* always the last entry */
ohneta 0:aae260bdcdd9 110 };
ohneta 0:aae260bdcdd9 111
ohneta 0:aae260bdcdd9 112 enum SCRIPTVAR_FLAGS {
ohneta 0:aae260bdcdd9 113 SCRIPTVAR_UNDEFINED = 0,
ohneta 0:aae260bdcdd9 114 SCRIPTVAR_FUNCTION = 1,
ohneta 0:aae260bdcdd9 115 SCRIPTVAR_OBJECT = 2,
ohneta 0:aae260bdcdd9 116 SCRIPTVAR_ARRAY = 4,
ohneta 0:aae260bdcdd9 117 SCRIPTVAR_DOUBLE = 8, // floating point double
ohneta 0:aae260bdcdd9 118 SCRIPTVAR_INTEGER = 16, // integer number
ohneta 0:aae260bdcdd9 119 SCRIPTVAR_STRING = 32, // string
ohneta 0:aae260bdcdd9 120 SCRIPTVAR_NULL = 64, // it seems null is its own data type
ohneta 0:aae260bdcdd9 121
ohneta 0:aae260bdcdd9 122 SCRIPTVAR_NATIVE = 128, // to specify this is a native function
ohneta 0:aae260bdcdd9 123 SCRIPTVAR_NUMERICMASK = SCRIPTVAR_NULL |
ohneta 0:aae260bdcdd9 124 SCRIPTVAR_DOUBLE |
ohneta 0:aae260bdcdd9 125 SCRIPTVAR_INTEGER,
ohneta 0:aae260bdcdd9 126 SCRIPTVAR_VARTYPEMASK = SCRIPTVAR_DOUBLE |
ohneta 0:aae260bdcdd9 127 SCRIPTVAR_INTEGER |
ohneta 0:aae260bdcdd9 128 SCRIPTVAR_STRING |
ohneta 0:aae260bdcdd9 129 SCRIPTVAR_FUNCTION |
ohneta 0:aae260bdcdd9 130 SCRIPTVAR_OBJECT |
ohneta 0:aae260bdcdd9 131 SCRIPTVAR_ARRAY |
ohneta 0:aae260bdcdd9 132 SCRIPTVAR_NULL,
ohneta 0:aae260bdcdd9 133
ohneta 0:aae260bdcdd9 134 };
ohneta 0:aae260bdcdd9 135
ohneta 0:aae260bdcdd9 136 #define TINYJS_RETURN_VAR "return"
ohneta 0:aae260bdcdd9 137 #define TINYJS_PROTOTYPE_CLASS "prototype"
ohneta 0:aae260bdcdd9 138 #define TINYJS_TEMP_NAME ""
ohneta 0:aae260bdcdd9 139 #define TINYJS_BLANK_DATA ""
ohneta 0:aae260bdcdd9 140
ohneta 0:aae260bdcdd9 141 /// convert the given string into a quoted string suitable for javascript
ohneta 0:aae260bdcdd9 142 std::string getJSString(const std::string &str);
ohneta 0:aae260bdcdd9 143
ohneta 0:aae260bdcdd9 144 class CScriptException {
ohneta 0:aae260bdcdd9 145 public:
ohneta 0:aae260bdcdd9 146 std::string text;
ohneta 0:aae260bdcdd9 147 CScriptException(const std::string &exceptionText);
ohneta 0:aae260bdcdd9 148 };
ohneta 0:aae260bdcdd9 149
ohneta 0:aae260bdcdd9 150 class CScriptLex
ohneta 0:aae260bdcdd9 151 {
ohneta 0:aae260bdcdd9 152 public:
ohneta 0:aae260bdcdd9 153 CScriptLex(const std::string &input);
ohneta 0:aae260bdcdd9 154 CScriptLex(CScriptLex *owner, int startChar, int endChar);
ohneta 0:aae260bdcdd9 155 ~CScriptLex(void);
ohneta 0:aae260bdcdd9 156
ohneta 0:aae260bdcdd9 157 char currCh, nextCh;
ohneta 0:aae260bdcdd9 158 int tk; ///< The type of the token that we have
ohneta 0:aae260bdcdd9 159 int tokenStart; ///< Position in the data at the beginning of the token we have here
ohneta 0:aae260bdcdd9 160 int tokenEnd; ///< Position in the data at the last character of the token we have here
ohneta 0:aae260bdcdd9 161 int tokenLastEnd; ///< Position in the data at the last character of the last token
ohneta 0:aae260bdcdd9 162 std::string tkStr; ///< Data contained in the token we have here
ohneta 0:aae260bdcdd9 163
ohneta 0:aae260bdcdd9 164 void match(int expected_tk); ///< Lexical match wotsit
ohneta 0:aae260bdcdd9 165 static std::string getTokenStr(int token); ///< Get the string representation of the given token
ohneta 0:aae260bdcdd9 166 void reset(); ///< Reset this lex so we can start again
ohneta 0:aae260bdcdd9 167
ohneta 0:aae260bdcdd9 168 std::string getSubString(int pos); ///< Return a sub-string from the given position up until right now
ohneta 0:aae260bdcdd9 169 CScriptLex *getSubLex(int lastPosition); ///< Return a sub-lexer from the given position up until right now
ohneta 0:aae260bdcdd9 170
ohneta 0:aae260bdcdd9 171 std::string getPosition(int pos=-1); ///< Return a string representing the position in lines and columns of the character pos given
ohneta 0:aae260bdcdd9 172
ohneta 0:aae260bdcdd9 173 protected:
ohneta 0:aae260bdcdd9 174 /* When we go into a loop, we use getSubLex to get a lexer for just the sub-part of the
ohneta 0:aae260bdcdd9 175 relevant string. This doesn't re-allocate and copy the string, but instead copies
ohneta 0:aae260bdcdd9 176 the data pointer and sets dataOwned to false, and dataStart/dataEnd to the relevant things. */
ohneta 0:aae260bdcdd9 177 char *data; ///< Data string to get tokens from
ohneta 0:aae260bdcdd9 178 int dataStart, dataEnd; ///< Start and end position in data string
ohneta 0:aae260bdcdd9 179 bool dataOwned; ///< Do we own this data string?
ohneta 0:aae260bdcdd9 180
ohneta 0:aae260bdcdd9 181 int dataPos; ///< Position in data (we CAN go past the end of the string here)
ohneta 0:aae260bdcdd9 182
ohneta 0:aae260bdcdd9 183 void getNextCh();
ohneta 0:aae260bdcdd9 184 void getNextToken(); ///< Get the text token from our text string
ohneta 0:aae260bdcdd9 185 };
ohneta 0:aae260bdcdd9 186
ohneta 0:aae260bdcdd9 187 class CScriptVar;
ohneta 0:aae260bdcdd9 188
ohneta 0:aae260bdcdd9 189 typedef void (*JSCallback)(CScriptVar *var, void *userdata);
ohneta 0:aae260bdcdd9 190
ohneta 0:aae260bdcdd9 191 class CScriptVarLink
ohneta 0:aae260bdcdd9 192 {
ohneta 0:aae260bdcdd9 193 public:
ohneta 0:aae260bdcdd9 194 std::string name;
ohneta 0:aae260bdcdd9 195 CScriptVarLink *nextSibling;
ohneta 0:aae260bdcdd9 196 CScriptVarLink *prevSibling;
ohneta 0:aae260bdcdd9 197 CScriptVar *var;
ohneta 0:aae260bdcdd9 198 bool owned;
ohneta 0:aae260bdcdd9 199
ohneta 0:aae260bdcdd9 200 CScriptVarLink(CScriptVar *var, const std::string &name = TINYJS_TEMP_NAME);
ohneta 0:aae260bdcdd9 201 CScriptVarLink(const CScriptVarLink &link); ///< Copy constructor
ohneta 0:aae260bdcdd9 202 ~CScriptVarLink();
ohneta 0:aae260bdcdd9 203 void replaceWith(CScriptVar *newVar); ///< Replace the Variable pointed to
ohneta 0:aae260bdcdd9 204 void replaceWith(CScriptVarLink *newVar); ///< Replace the Variable pointed to (just dereferences)
ohneta 0:aae260bdcdd9 205 int getIntName(); ///< Get the name as an integer (for arrays)
ohneta 0:aae260bdcdd9 206 void setIntName(int n); ///< Set the name as an integer (for arrays)
ohneta 0:aae260bdcdd9 207 };
ohneta 0:aae260bdcdd9 208
ohneta 0:aae260bdcdd9 209 /// Variable class (containing a doubly-linked list of children)
ohneta 0:aae260bdcdd9 210 class CScriptVar
ohneta 0:aae260bdcdd9 211 {
ohneta 0:aae260bdcdd9 212 public:
ohneta 0:aae260bdcdd9 213 CScriptVar(); ///< Create undefined
ohneta 0:aae260bdcdd9 214 CScriptVar(const std::string &varData, int varFlags); ///< User defined
ohneta 0:aae260bdcdd9 215 CScriptVar(const std::string &str); ///< Create a string
ohneta 0:aae260bdcdd9 216 CScriptVar(double varData);
ohneta 0:aae260bdcdd9 217 CScriptVar(int val);
ohneta 0:aae260bdcdd9 218 ~CScriptVar(void);
ohneta 0:aae260bdcdd9 219
ohneta 0:aae260bdcdd9 220 CScriptVar *getReturnVar(); ///< If this is a function, get the result value (for use by native functions)
ohneta 0:aae260bdcdd9 221 void setReturnVar(CScriptVar *var); ///< Set the result value. Use this when setting complex return data as it avoids a deepCopy()
ohneta 0:aae260bdcdd9 222 CScriptVar *getParameter(const std::string &name); ///< If this is a function, get the parameter with the given name (for use by native functions)
ohneta 0:aae260bdcdd9 223
ohneta 0:aae260bdcdd9 224 CScriptVarLink *findChild(const std::string &childName); ///< Tries to find a child with the given name, may return 0
ohneta 0:aae260bdcdd9 225 CScriptVarLink *findChildOrCreate(const std::string &childName, int varFlags=SCRIPTVAR_UNDEFINED); ///< Tries to find a child with the given name, or will create it with the given flags
ohneta 0:aae260bdcdd9 226 CScriptVarLink *findChildOrCreateByPath(const std::string &path); ///< Tries to find a child with the given path (separated by dots)
ohneta 0:aae260bdcdd9 227 CScriptVarLink *addChild(const std::string &childName, CScriptVar *child=NULL);
ohneta 0:aae260bdcdd9 228 CScriptVarLink *addChildNoDup(const std::string &childName, CScriptVar *child=NULL); ///< add a child overwriting any with the same name
ohneta 0:aae260bdcdd9 229 void removeChild(CScriptVar *child);
ohneta 0:aae260bdcdd9 230 void removeLink(CScriptVarLink *link); ///< Remove a specific link (this is faster than finding via a child)
ohneta 0:aae260bdcdd9 231 void removeAllChildren();
ohneta 0:aae260bdcdd9 232 CScriptVar *getArrayIndex(int idx); ///< The the value at an array index
ohneta 0:aae260bdcdd9 233 void setArrayIndex(int idx, CScriptVar *value); ///< Set the value at an array index
ohneta 0:aae260bdcdd9 234 int getArrayLength(); ///< If this is an array, return the number of items in it (else 0)
ohneta 0:aae260bdcdd9 235 int getChildren(); ///< Get the number of children
ohneta 0:aae260bdcdd9 236
ohneta 0:aae260bdcdd9 237 int getInt();
ohneta 0:aae260bdcdd9 238 bool getBool() { return getInt() != 0; }
ohneta 0:aae260bdcdd9 239 double getDouble();
ohneta 0:aae260bdcdd9 240 const std::string &getString();
ohneta 0:aae260bdcdd9 241 std::string getParsableString(); ///< get Data as a parsable javascript string
ohneta 0:aae260bdcdd9 242 void setInt(int num);
ohneta 0:aae260bdcdd9 243 void setDouble(double val);
ohneta 0:aae260bdcdd9 244 void setString(const std::string &str);
ohneta 0:aae260bdcdd9 245 void setUndefined();
ohneta 0:aae260bdcdd9 246 void setArray();
ohneta 0:aae260bdcdd9 247 bool equals(CScriptVar *v);
ohneta 0:aae260bdcdd9 248
ohneta 0:aae260bdcdd9 249 bool isInt() { return (flags&SCRIPTVAR_INTEGER)!=0; }
ohneta 0:aae260bdcdd9 250 bool isDouble() { return (flags&SCRIPTVAR_DOUBLE)!=0; }
ohneta 0:aae260bdcdd9 251 bool isString() { return (flags&SCRIPTVAR_STRING)!=0; }
ohneta 0:aae260bdcdd9 252 bool isNumeric() { return (flags&SCRIPTVAR_NUMERICMASK)!=0; }
ohneta 0:aae260bdcdd9 253 bool isFunction() { return (flags&SCRIPTVAR_FUNCTION)!=0; }
ohneta 0:aae260bdcdd9 254 bool isObject() { return (flags&SCRIPTVAR_OBJECT)!=0; }
ohneta 0:aae260bdcdd9 255 bool isArray() { return (flags&SCRIPTVAR_ARRAY)!=0; }
ohneta 0:aae260bdcdd9 256 bool isNative() { return (flags&SCRIPTVAR_NATIVE)!=0; }
ohneta 0:aae260bdcdd9 257 bool isUndefined() { return (flags & SCRIPTVAR_VARTYPEMASK) == SCRIPTVAR_UNDEFINED; }
ohneta 0:aae260bdcdd9 258 bool isNull() { return (flags & SCRIPTVAR_NULL)!=0; }
ohneta 0:aae260bdcdd9 259 bool isBasic() { return firstChild==0; } ///< Is this *not* an array/object/etc
ohneta 0:aae260bdcdd9 260
ohneta 0:aae260bdcdd9 261 CScriptVar *mathsOp(CScriptVar *b, int op); ///< do a maths op with another script variable
ohneta 0:aae260bdcdd9 262 void copyValue(CScriptVar *val); ///< copy the value from the value given
ohneta 0:aae260bdcdd9 263 CScriptVar *deepCopy(); ///< deep copy this node and return the result
ohneta 0:aae260bdcdd9 264
ohneta 0:aae260bdcdd9 265 void trace(std::string indentStr = "", const std::string &name = ""); ///< Dump out the contents of this using trace
ohneta 0:aae260bdcdd9 266 std::string getFlagsAsString(); ///< For debugging - just dump a string version of the flags
ohneta 0:aae260bdcdd9 267 #ifndef MBED
ohneta 0:aae260bdcdd9 268 void getJSON(std::ostringstream &destination, const std::string linePrefix=""); ///< Write out all the JS code needed to recreate this script variable to the stream (as JSON)
ohneta 0:aae260bdcdd9 269 #else
ohneta 0:aae260bdcdd9 270 void getJSON(std::string &destination, const std::string linePrefix=""); ///< Write out all the JS code needed to recreate this script variable to the stream (as JSON)
ohneta 0:aae260bdcdd9 271 #endif
ohneta 0:aae260bdcdd9 272 void setCallback(JSCallback callback, void *userdata); ///< Set the callback for native functions
ohneta 0:aae260bdcdd9 273
ohneta 0:aae260bdcdd9 274 CScriptVarLink *firstChild;
ohneta 0:aae260bdcdd9 275 CScriptVarLink *lastChild;
ohneta 0:aae260bdcdd9 276
ohneta 0:aae260bdcdd9 277 /// For memory management/garbage collection
ohneta 0:aae260bdcdd9 278 CScriptVar *ref(); ///< Add reference to this variable
ohneta 0:aae260bdcdd9 279 void unref(); ///< Remove a reference, and delete this variable if required
ohneta 0:aae260bdcdd9 280 int getRefs(); ///< Get the number of references to this script variable
ohneta 0:aae260bdcdd9 281 protected:
ohneta 0:aae260bdcdd9 282 int refs; ///< The number of references held to this - used for garbage collection
ohneta 0:aae260bdcdd9 283
ohneta 0:aae260bdcdd9 284 std::string data; ///< The contents of this variable if it is a string
ohneta 0:aae260bdcdd9 285 long intData; ///< The contents of this variable if it is an int
ohneta 0:aae260bdcdd9 286 double doubleData; ///< The contents of this variable if it is a double
ohneta 0:aae260bdcdd9 287 int flags; ///< the flags determine the type of the variable - int/double/string/etc
ohneta 0:aae260bdcdd9 288 JSCallback jsCallback; ///< Callback for native functions
ohneta 0:aae260bdcdd9 289 void *jsCallbackUserData; ///< user data passed as second argument to native functions
ohneta 0:aae260bdcdd9 290
ohneta 0:aae260bdcdd9 291 void init(); ///< initialisation of data members
ohneta 0:aae260bdcdd9 292
ohneta 0:aae260bdcdd9 293 /** Copy the basic data and flags from the variable given, with no
ohneta 0:aae260bdcdd9 294 * children. Should be used internally only - by copyValue and deepCopy */
ohneta 0:aae260bdcdd9 295 void copySimpleData(CScriptVar *val);
ohneta 0:aae260bdcdd9 296
ohneta 0:aae260bdcdd9 297 friend class CTinyJS;
ohneta 0:aae260bdcdd9 298 };
ohneta 0:aae260bdcdd9 299
ohneta 0:aae260bdcdd9 300 class CTinyJS {
ohneta 0:aae260bdcdd9 301 public:
ohneta 0:aae260bdcdd9 302 CTinyJS();
ohneta 0:aae260bdcdd9 303 ~CTinyJS();
ohneta 0:aae260bdcdd9 304
ohneta 0:aae260bdcdd9 305 void execute(const std::string &code);
ohneta 0:aae260bdcdd9 306 /** Evaluate the given code and return a link to a javascript object,
ohneta 0:aae260bdcdd9 307 * useful for (dangerous) JSON parsing. If nothing to return, will return
ohneta 0:aae260bdcdd9 308 * 'undefined' variable type. CScriptVarLink is returned as this will
ohneta 0:aae260bdcdd9 309 * automatically unref the result as it goes out of scope. If you want to
ohneta 0:aae260bdcdd9 310 * keep it, you must use ref() and unref() */
ohneta 0:aae260bdcdd9 311 CScriptVarLink evaluateComplex(const std::string &code);
ohneta 0:aae260bdcdd9 312 /** Evaluate the given code and return a string. If nothing to return, will return
ohneta 0:aae260bdcdd9 313 * 'undefined' */
ohneta 0:aae260bdcdd9 314 std::string evaluate(const std::string &code);
ohneta 0:aae260bdcdd9 315
ohneta 0:aae260bdcdd9 316 /// add a native function to be called from TinyJS
ohneta 0:aae260bdcdd9 317 /** example:
ohneta 0:aae260bdcdd9 318 \code
ohneta 0:aae260bdcdd9 319 void scRandInt(CScriptVar *c, void *userdata) { ... }
ohneta 0:aae260bdcdd9 320 tinyJS->addNative("function randInt(min, max)", scRandInt, 0);
ohneta 0:aae260bdcdd9 321 \endcode
ohneta 0:aae260bdcdd9 322
ohneta 0:aae260bdcdd9 323 or
ohneta 0:aae260bdcdd9 324
ohneta 0:aae260bdcdd9 325 \code
ohneta 0:aae260bdcdd9 326 void scSubstring(CScriptVar *c, void *userdata) { ... }
ohneta 0:aae260bdcdd9 327 tinyJS->addNative("function String.substring(lo, hi)", scSubstring, 0);
ohneta 0:aae260bdcdd9 328 \endcode
ohneta 0:aae260bdcdd9 329 */
ohneta 0:aae260bdcdd9 330 void addNative(const std::string &funcDesc, JSCallback ptr, void *userdata);
ohneta 0:aae260bdcdd9 331
ohneta 0:aae260bdcdd9 332 /// Get the given variable specified by a path (var1.var2.etc), or return 0
ohneta 0:aae260bdcdd9 333 CScriptVar *getScriptVariable(const std::string &path);
ohneta 0:aae260bdcdd9 334 /// Get the value of the given variable, or return 0
ohneta 0:aae260bdcdd9 335 const std::string *getVariable(const std::string &path);
ohneta 0:aae260bdcdd9 336 /// set the value of the given variable, return trur if it exists and gets set
ohneta 0:aae260bdcdd9 337 bool setVariable(const std::string &path, const std::string &varData);
ohneta 0:aae260bdcdd9 338
ohneta 0:aae260bdcdd9 339 /// Send all variables to stdout
ohneta 0:aae260bdcdd9 340 void trace();
ohneta 0:aae260bdcdd9 341
ohneta 0:aae260bdcdd9 342 CScriptVar *root; /// root of symbol table
ohneta 0:aae260bdcdd9 343 private:
ohneta 0:aae260bdcdd9 344 CScriptLex *l; /// current lexer
ohneta 0:aae260bdcdd9 345 std::vector<CScriptVar*> scopes; /// stack of scopes when parsing
ohneta 0:aae260bdcdd9 346 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 347 std::vector<std::string> call_stack; /// Names of places called so we can show when erroring
ohneta 0:aae260bdcdd9 348 #endif
ohneta 0:aae260bdcdd9 349
ohneta 0:aae260bdcdd9 350 CScriptVar *stringClass; /// Built in string class
ohneta 0:aae260bdcdd9 351 CScriptVar *objectClass; /// Built in object class
ohneta 0:aae260bdcdd9 352 CScriptVar *arrayClass; /// Built in array class
ohneta 0:aae260bdcdd9 353
ohneta 0:aae260bdcdd9 354 // parsing - in order of precedence
ohneta 0:aae260bdcdd9 355 CScriptVarLink *functionCall(bool &execute, CScriptVarLink *function, CScriptVar *parent);
ohneta 0:aae260bdcdd9 356 CScriptVarLink *factor(bool &execute);
ohneta 0:aae260bdcdd9 357 CScriptVarLink *unary(bool &execute);
ohneta 0:aae260bdcdd9 358 CScriptVarLink *term(bool &execute);
ohneta 0:aae260bdcdd9 359 CScriptVarLink *expression(bool &execute);
ohneta 0:aae260bdcdd9 360 CScriptVarLink *shift(bool &execute);
ohneta 0:aae260bdcdd9 361 CScriptVarLink *condition(bool &execute);
ohneta 0:aae260bdcdd9 362 CScriptVarLink *logic(bool &execute);
ohneta 0:aae260bdcdd9 363 CScriptVarLink *ternary(bool &execute);
ohneta 0:aae260bdcdd9 364 CScriptVarLink *base(bool &execute);
ohneta 0:aae260bdcdd9 365 void block(bool &execute);
ohneta 0:aae260bdcdd9 366 void statement(bool &execute);
ohneta 0:aae260bdcdd9 367 // parsing utility functions
ohneta 0:aae260bdcdd9 368 CScriptVarLink *parseFunctionDefinition();
ohneta 0:aae260bdcdd9 369 void parseFunctionArguments(CScriptVar *funcVar);
ohneta 0:aae260bdcdd9 370
ohneta 0:aae260bdcdd9 371 CScriptVarLink *findInScopes(const std::string &childName); ///< Finds a child, looking recursively up the scopes
ohneta 0:aae260bdcdd9 372 /// Look up in any parent classes of the given object
ohneta 0:aae260bdcdd9 373 CScriptVarLink *findInParentClasses(CScriptVar *object, const std::string &name);
ohneta 0:aae260bdcdd9 374 };
ohneta 0:aae260bdcdd9 375
ohneta 0:aae260bdcdd9 376 #endif
ohneta 0:aae260bdcdd9 377