Skip to content

Commit

Permalink
Adds support for multiple var declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
ndreynolds committed Sep 29, 2012
1 parent a934bc1 commit 59658b0
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 34 deletions.
49 changes: 27 additions & 22 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ fh_eval(JSValue *ctx, Node *node)
case NODE_TERN: return fh_if(ctx, node);
case NODE_ASGN: return fh_assign(ctx, node);
case NODE_RETURN: return fh_return(ctx, node);
case NODE_VAR_STMT: return fh_eval(ctx, node->e1);
case NODE_VAR_DEC_LST: return fh_eval_each(ctx, node);
case NODE_VAR_DEC: return fh_var_dec(ctx, node);
case NODE_BREAK: return fh_break();
case NODE_PROP_LST: return fh_prop_lst(ctx, node);
case NODE_PROP_LST: return fh_eval_each(ctx, node);
case NODE_PROP: fh_set(ctx, node->e1->sval, fh_eval(ctx, node->e2)); break;
case NODE_WHILE: fh_while(ctx, node->e1, node->e2); break;
case NODE_FOR: fh_for(ctx, node->e1, node->e2); break;
case NODE_FORIN: fh_forin(ctx, node); break;
case NODE_VAR_STMT: fh_var_stmt(ctx, node); break;
case NODE_EMPT_STMT: break;
default:
fh_error(
Expand All @@ -61,6 +63,15 @@ fh_eval(JSValue *ctx, Node *node)
return result;
}

JSValue *
fh_eval_each(JSValue *ctx, Node *node)
{
JSValue *result = JSUNDEF();
rewind_node(node);
while(!node->visited) result = fh_eval(ctx, pop_node(node));
return result;
}

JSValue *
fh_exp(JSValue *ctx, Node *node)
{
Expand All @@ -74,6 +85,16 @@ fh_exp(JSValue *ctx, Node *node)
}
}

JSValue *
fh_var_dec(JSValue *ctx, Node *node)
{
if (node->e2 != NULL)
fh_set(ctx, node->e1->sval, fh_eval(ctx, node->e2));
else
fh_set(ctx, node->e1->sval, JSUNDEF());
return JSUNDEF();
}

JSValue *
fh_if(JSValue *ctx, Node *node)
{
Expand Down Expand Up @@ -101,24 +122,6 @@ fh_break()
return signal;
}

void
fh_var_stmt(JSValue *ctx, Node *node)
{
if (node->e2 != NULL)
fh_set(ctx, node->e1->sval, fh_eval(ctx, node->e2));
else
fh_set(ctx, node->e1->sval, JSNULL());
}

JSValue *
fh_prop_lst(JSValue *ctx, Node *node)
{
JSValue *result = JSUNDEF();
rewind_node(node);
while(!node->visited) result = fh_eval(ctx, pop_node(node));
return result;
}

JSValue *
fh_stmt_lst(JSValue *ctx, Node *node)
{
Expand Down Expand Up @@ -274,8 +277,10 @@ fh_forin(JSValue *ctx, Node *node)
*name = fh_str_from_node(ctx, node->e1);

// If variable declaration:
if (node->e1->type == NODE_IDENT)
fh_set(ctx, name->string.ptr, JSNULL());
if (node->e1->type == NODE_VAR_DEC) {
fh_eval(ctx, node->e1);
name = JSSTR(node->e1->e1->sval);
}

// Note that during the first iteration, the prototype is the object.
while(proto != NULL) {
Expand Down
3 changes: 2 additions & 1 deletion src/eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
void fh_while(JSValue *, Node *, Node *);
void fh_for(JSValue *, Node *, Node *);
void fh_forin(JSValue *, Node *);
void fh_var_stmt(JSValue *, Node *);
void fh_do_assign(JSValue *, char *, JSValue *, char *);
JSArgs * fh_build_args(JSValue *, Node *);
JSValue * fh_break(void);
JSValue * fh_eval(JSValue *, Node *);
JSValue * fh_eval_each(JSValue *, Node *);
JSValue * fh_exp(JSValue *, Node *);
JSValue * fh_if(JSValue *, Node *);
JSValue * fh_assign(JSValue *, Node *);
Expand All @@ -43,6 +43,7 @@ JSValue * fh_src_lst(JSValue *, Node *);
JSValue * fh_obj(JSValue *, Node *);
JSValue * fh_arr(JSValue *, Node *);
JSValue * fh_call(JSValue *, Node *);
JSValue * fh_var_dec(JSValue *, Node *);
JSValue * fh_function_call(JSValue *, State *, JSValue *, Node *);
JSValue * fh_setup_func_env(JSValue *, JSValue *, JSArgs *);
JSValue * fh_str_from_node(JSValue *, Node *);
Expand Down
39 changes: 28 additions & 11 deletions src/grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

#define NEW_NODE(t,e1,e2,e3,d,s) new_node(t,e1,e2,e3,d,s,yylloc.first_line,yylloc.first_column)
#define NEW_IDENT(name) NEW_NODE(NODE_IDENT,0,0,0,0,name)
#define NEW_VARSTMT(ident,exp) NEW_NODE(NODE_VAR_STMT,ident,exp,0,0,0)
#define NEW_WHILE(cnd,blck) NEW_NODE(NODE_WHILE,cnd,blck,0,0,0)
#define NEW_DOWHILE(cnd,blck) NEW_NODE(NODE_DOWHILE,cnd,blck,0,0,0)
#define NEW_BLOCK(stmtlst) NEW_NODE(NODE_BLOCK,stmtlst,0,0,0,0)
Expand Down Expand Up @@ -69,6 +68,9 @@
#define NEW_PARAMLST(head,tail) NEW_NODE(NODE_PARAM_LST,head,tail,0,0,0)
#define NEW_ELISION() NEW_NODE(NODE_ELISION,0,0,0,0,0)
#define NEW_SRCLST(head,tail) NEW_NODE(NODE_SRC_LST,head,tail,0,0,0)
#define NEW_VARSTMT(declst) NEW_NODE(NODE_VAR_STMT,declst,0,0,0,0)
#define NEW_VARDEC(id,exp) NEW_NODE(NODE_VAR_DEC,id,exp,0,0,0)
#define NEW_VARDECLST(head,tail) NEW_NODE(NODE_VAR_DEC_LST,head,tail,0,0,0)

void yyerror(const char *);
int yylex(void);
Expand Down Expand Up @@ -142,7 +144,8 @@
%type<node> AssignmentExpression ElementList PropertyName PropertyAssignment
%type<node> PropertyNameAndValueList Function FunctionBody FunctionExpression
%type<node> FormalParameterList CallExpression MemberExpression NewExpression
%type<node> Arguments ArgumentList Elision
%type<node> Arguments ArgumentList Elision VariableDeclarationList
%type<node> VariableDeclaration Initializer

%%

Expand Down Expand Up @@ -192,10 +195,24 @@ StatementList : Statement
{ $$ = NEW_STMTLST($2, $1); }
;

VariableStatement : VAR Identifier ';'
{ $$ = NEW_VARSTMT($2, NULL); }
| VAR Identifier '=' AssignmentExpression ';'
{ $$ = NEW_VARSTMT($2, $4); }
VariableStatement : VAR VariableDeclarationList ';'
{ $$ = NEW_VARSTMT($2); }
;

VariableDeclarationList : VariableDeclaration
{ $$ = NEW_VARDECLST($1, NULL); }
| VariableDeclarationList ',' VariableDeclaration
{ $$ = NEW_VARDECLST($3, $1); }
;

VariableDeclaration : Identifier Initializer
{ $$ = NEW_VARDEC($1, $2); }
| Identifier
{ $$ = NEW_VARDEC($1, NULL); }
;

Initializer : '=' AssignmentExpression
{ $$ = $2; }
;

EmptyStatement : ';'
Expand All @@ -221,26 +238,26 @@ IterationStatement : DO Statement WHILE '(' Expression ')' ';'

| FOR '(' LeftHandSideExpression IN Expression ')' Statement
{ $$ = NEW_FORIN($3, $5, $7); }
| FOR '(' VAR Identifier IN Expression ')' Statement
| FOR '(' VAR VariableDeclaration IN Expression ')' Statement
{ $$ = NEW_FORIN($4, $6, $8); }

/* for ( Expression/VarDecl ; Expresion ; Expression ) Statement */

| FOR '(' Expression ';' Expression ';' Expression ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($3, $5, $7), $9); }
| FOR '(' VAR Identifier ';' Expression ';' Expression ')' Statement
| FOR '(' VAR VariableDeclarationList ';' Expression ';' Expression ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($4, $6, $8), $10); }
| FOR '(' Expression ';' Expression ';' ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($3, $5, NULL), $8); }
| FOR '(' VAR Identifier ';' Expression ';' ')' Statement
| FOR '(' VAR VariableDeclarationList ';' Expression ';' ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($4, $6, NULL), $9); }
| FOR '(' Expression ';' ';' Expression ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($3, NULL, $6), $8); }
| FOR '(' VAR Identifier ';' ';' Expression ')' Statement
| FOR '(' VAR VariableDeclarationList ';' ';' Expression ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($4, NULL, $7), $9); }
| FOR '(' Expression ';' ';' ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($3, NULL, NULL), $7); }
| FOR '(' VAR Identifier ';' ';' ')' Statement
| FOR '(' VAR VariableDeclarationList ';' ';' ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP($4, NULL, NULL), $8); }
| FOR '(' ';' Expression ';' Expression ')' Statement
{ $$ = NEW_FOR(NEW_EXPGRP(NULL, $4, $6), $8); }
Expand Down
2 changes: 2 additions & 0 deletions src/nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ enum NodeType {
NODE_NULL,
NODE_ASGN,
NODE_VAR_STMT,
NODE_VAR_DEC,
NODE_VAR_DEC_LST,
NODE_EMPT_STMT,
NODE_EXP_STMT,
NODE_EXP,
Expand Down
11 changes: 11 additions & 0 deletions test/test_declarations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var assert = console.assert;

// Single variable declaration.
var a = 12;
assert(a === 12);

// Multiple variables.
var b = 42, c = 'foobar', d;
assert(b === 42);
assert(c === 'foobar');
assert(d === undefined);

0 comments on commit 59658b0

Please sign in to comment.