blob: 63b8b63e52d52cc252500f3587bc53434fcc6fe0 [file] [log] [blame]
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "function_object.h"
#include "lexer.h"
#include "nodes.h"
#include "error_object.h"
extern int kjsyyparse();
using namespace KJS;
FunctionObject::FunctionObject(const Object& funcProto)
: ConstructorImp(funcProto, 1)
{
// ECMA 15.3.3.1 Function.prototype
setPrototypeProperty(funcProto);
}
// ECMA 15.3.1 The Function Constructor Called as a Function
Completion FunctionObject::execute(const List &args)
{
return Completion(ReturnValue, construct(args));
}
// ECMA 15.3.2 The Function Constructor
Object FunctionObject::construct(const List &args)
{
UString p("");
UString body;
int argsSize = args.size();
if (argsSize == 0) {
body = "";
} else if (argsSize == 1) {
body = args[0].toString().value();
} else {
p = args[0].toString().value();
for (int k = 1; k < argsSize - 1; k++)
p += "," + args[k].toString().value();
body = args[argsSize-1].toString().value();
}
Lexer::curr()->setCode(body.data(), body.size());
KJScriptImp::current()->pushStack();
int yp = kjsyyparse();
ProgramNode *progNode = KJScriptImp::current()->progNode();
KJScriptImp::current()->popStack();
if (yp) {
/* TODO: free nodes */
return ErrorObject::create(SyntaxError,
I18N_NOOP("Syntax error in function body"), -1);
}
List scopeChain;
scopeChain.append(Global::current());
FunctionBodyNode *bodyNode = progNode;
FunctionImp *fimp = new DeclaredFunctionImp(UString::null, bodyNode,
&scopeChain);
Object ret(fimp); // protect from GC
// parse parameter list. throw syntax error on illegal identifiers
int len = p.size();
const UChar *c = p.data();
int i = 0, params = 0;
UString param;
while (i < len) {
while (*c == ' ' && i < len)
c++, i++;
if (Lexer::isIdentLetter(c->unicode())) { // else error
param = UString(c, 1);
c++, i++;
while (i < len && (Lexer::isIdentLetter(c->unicode()) ||
Lexer::isDecimalDigit(c->unicode()))) {
param += UString(c, 1);
c++, i++;
}
while (i < len && *c == ' ')
c++, i++;
if (i == len) {
fimp->addParameter(param);
params++;
break;
} else if (*c == ',') {
fimp->addParameter(param);
params++;
c++, i++;
continue;
} // else error
}
return ErrorObject::create(SyntaxError,
I18N_NOOP("Syntax error in parameter list"),
-1);
}
fimp->setLength(params);
fimp->setPrototypeProperty(Global::current().functionPrototype());
return ret;
}
FunctionPrototype::FunctionPrototype(const Object &p)
: ObjectImp(FunctionClass, Null(), p)
{
}