Version 0.29 : Added new object via functions

Fixed getString() for double on some platforms
master
pur3mail 13 years ago
parent 8c790516ea
commit ecc4cc8fbd

@ -92,9 +92,10 @@
Rudimentary call stack on error
Added String Character functions
Added shift operators
Version 0.29 : Added new object via functions
Fixed getString() for double on some platforms
NOTE: This doesn't support constructors for objects
NOTE:
Constructing an array with an initial length 'Array(5)' doesn't work
Recursive loops of data such as a.foo = a; fail to be garbage collected
length variable cannot be set
@ -951,7 +952,7 @@ const string &CScriptVar::getString() {
}
if (isDouble()) {
char buffer[32];
sprintf_s(buffer, sizeof(buffer), "%lf", doubleData);
sprintf_s(buffer, sizeof(buffer), "%f", doubleData);
data = buffer;
return data;
}
@ -1429,47 +1430,15 @@ CScriptVarLink *CTinyJS::parseFunctionDefinition() {
return funcVar;
}
CScriptVarLink *CTinyJS::factor(bool &execute) {
if (l->tk=='(') {
l->match('(');
CScriptVarLink *a = base(execute);
l->match(')');
return a;
}
if (l->tk==LEX_R_TRUE) {
l->match(LEX_R_TRUE);
return new CScriptVarLink(new CScriptVar(1));
}
if (l->tk==LEX_R_FALSE) {
l->match(LEX_R_FALSE);
return new CScriptVarLink(new CScriptVar(0));
}
if (l->tk==LEX_R_NULL) {
l->match(LEX_R_NULL);
return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_NULL));
}
if (l->tk==LEX_R_UNDEFINED) {
l->match(LEX_R_UNDEFINED);
return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_UNDEFINED));
}
if (l->tk==LEX_ID) {
CScriptVarLink *a = execute ? findInScopes(l->tkStr) : new CScriptVarLink(new CScriptVar());
//printf("0x%08X for %s at %s\n", (unsigned int)a, l->tkStr.c_str(), l->getPosition().c_str());
/* The parent if we're executing a method call */
CScriptVar *parent = 0;
if (execute && !a) {
/* Variable doesn't exist! JavaScript says we should create it
* (we won't add it here. This is done in the assignment operator)*/
a = new CScriptVarLink(new CScriptVar(), l->tkStr);
}
l->match(LEX_ID);
while (l->tk=='(' || l->tk=='.' || l->tk=='[') {
if (l->tk=='(') { // ------------------------------------- Function Call
/** Handle a function call (assumes we've parsed the function name and we're
* on the start bracket). 'parent' is the object that contains this method,
* if there was one (otherwise it's just a normnal function).
*/
CScriptVarLink *CTinyJS::functionCall(bool &execute, CScriptVarLink *function, CScriptVar *parent) {
if (execute) {
if (!a->var->isFunction()) {
if (!function->var->isFunction()) {
string errorMsg = "Expecting '";
errorMsg = errorMsg + a->name + "' to be a function";
errorMsg = errorMsg + function->name + "' to be a function";
throw new CScriptException(errorMsg.c_str());
}
l->match('(');
@ -1478,7 +1447,7 @@ CScriptVarLink *CTinyJS::factor(bool &execute) {
if (parent)
functionRoot->addChildNoDup("this", parent);
// grab in all parameters
CScriptVarLink *v = a->var->firstChild;
CScriptVarLink *v = function->var->firstChild;
while (v) {
CScriptVarLink *value = base(execute);
if (execute) {
@ -1502,19 +1471,19 @@ CScriptVarLink *CTinyJS::factor(bool &execute) {
CScriptVarLink *returnVarLink = functionRoot->addChild(TINYJS_RETURN_VAR);
scopes.push_back(functionRoot);
#ifdef TINYJS_CALL_STACK
call_stack.push_back(a->name + " from " + l->getPosition());
call_stack.push_back(function->name + " from " + l->getPosition());
#endif
if (a->var->isNative()) {
ASSERT(a->var->jsCallback);
a->var->jsCallback(functionRoot, a->var->jsCallbackUserData);
if (function->var->isNative()) {
ASSERT(function->var->jsCallback);
function->var->jsCallback(functionRoot, function->var->jsCallbackUserData);
} else {
/* we just want to execute the block, but something could
* have messed up and left us with the wrong ScriptLex, so
* we want to be careful here... */
CScriptException *exception = 0;
CScriptLex *oldLex = l;
CScriptLex *newLex = new CScriptLex(a->var->getString());
CScriptLex *newLex = new CScriptLex(function->var->getString());
l = newLex;
try {
block(execute);
@ -1538,9 +1507,9 @@ CScriptVarLink *CTinyJS::factor(bool &execute) {
functionRoot->removeLink(returnVarLink);
delete functionRoot;
if (returnVar)
a = returnVar;
return returnVar;
else
a = new CScriptVarLink(new CScriptVar());
return new CScriptVarLink(new CScriptVar());
} else {
// function, but not executing - just parse args and be done
l->match('(');
@ -1553,7 +1522,50 @@ CScriptVarLink *CTinyJS::factor(bool &execute) {
if (l->tk == '{') {
block(execute);
}
/* function will be a blank scriptvarlink if we're not executing,
* so just return it rather than an alloc/free */
return function;
}
}
CScriptVarLink *CTinyJS::factor(bool &execute) {
if (l->tk=='(') {
l->match('(');
CScriptVarLink *a = base(execute);
l->match(')');
return a;
}
if (l->tk==LEX_R_TRUE) {
l->match(LEX_R_TRUE);
return new CScriptVarLink(new CScriptVar(1));
}
if (l->tk==LEX_R_FALSE) {
l->match(LEX_R_FALSE);
return new CScriptVarLink(new CScriptVar(0));
}
if (l->tk==LEX_R_NULL) {
l->match(LEX_R_NULL);
return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_NULL));
}
if (l->tk==LEX_R_UNDEFINED) {
l->match(LEX_R_UNDEFINED);
return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_UNDEFINED));
}
if (l->tk==LEX_ID) {
CScriptVarLink *a = execute ? findInScopes(l->tkStr) : new CScriptVarLink(new CScriptVar());
//printf("0x%08X for %s at %s\n", (unsigned int)a, l->tkStr.c_str(), l->getPosition().c_str());
/* The parent if we're executing a method call */
CScriptVar *parent = 0;
if (execute && !a) {
/* Variable doesn't exist! JavaScript says we should create it
* (we won't add it here. This is done in the assignment operator)*/
a = new CScriptVarLink(new CScriptVar(), l->tkStr);
}
l->match(LEX_ID);
while (l->tk=='(' || l->tk=='.' || l->tk=='[') {
if (l->tk=='(') { // ------------------------------------- Function Call
a = functionCall(execute, a, parent);
} else if (l->tk == '.') { // ------------------------------------- Record Access
l->match('.');
if (execute) {
@ -1656,20 +1668,24 @@ CScriptVarLink *CTinyJS::factor(bool &execute) {
l->match(LEX_R_NEW);
const string &className = l->tkStr;
if (execute) {
CScriptVarLink *objClass = findInScopes(className);
if (!objClass) {
CScriptVarLink *objClassOrFunc = findInScopes(className);
if (!objClassOrFunc) {
TRACE("%s is not a valid class name", className.c_str());
return new CScriptVarLink(new CScriptVar());
}
l->match(LEX_ID);
CScriptVar *obj = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT);
obj->addChild(TINYJS_PROTOTYPE_CLASS, objClass->var);
CScriptVarLink *objLink = new CScriptVarLink(obj);
if (objClassOrFunc->var->isFunction()) {
CLEAN(functionCall(execute, objClassOrFunc, obj));
} else {
obj->addChild(TINYJS_PROTOTYPE_CLASS, objClassOrFunc->var);
if (l->tk == '(') {
l->match('(');
l->match(')');
}
// TODO: Object constructors
return new CScriptVarLink(obj);
}
return objLink;
} else {
l->match(LEX_ID);
if (l->tk == '(') {

@ -333,6 +333,7 @@ private:
CScriptVar *arrayClass; /// Built in array class
// parsing - in order of precedence
CScriptVarLink *functionCall(bool &execute, CScriptVarLink *function, CScriptVar *parent);
CScriptVarLink *factor(bool &execute);
CScriptVarLink *unary(bool &execute);
CScriptVarLink *term(bool &execute);

@ -0,0 +1,10 @@
// the 'lf' in the printf caused issues writing doubles on some compilers
function Person(name) {
this.name = name;
this.kill = function() { this.name += " is dead"; };
}
var a = new Person("Kenny");
a.kill();
result = a.name == "Kenny is dead";

@ -0,0 +1,9 @@
// the 'lf' in the printf caused issues writing doubles on some compilers
var a=5.0/10.0*100.0;
var b=5.0*110.0;
var c=50.0/10.0;
a.dump();
b.dump();
c.dump();
result = a==50 && b==550 && c==5;
Loading…
Cancel
Save