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

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