Skip to content

Commit

Permalink
refactor: use Pratt's parser in {let} blocks
Browse files Browse the repository at this point in the history
Closes #280
  • Loading branch information
PK1A committed Sep 3, 2014
1 parent 5225e08 commit 5facfb4
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 107 deletions.
26 changes: 15 additions & 11 deletions hsp/compiler/jsgenerator/processors.js
Expand Up @@ -54,7 +54,7 @@ exports["template"] = function (node, walker) {
for (var i=0; i < globalsLength; i++) {
gnm=globals[i];
globalsStatement.push( "try {_" + gnm + "=", gnm ,"} catch(e) {_" + gnm + "=n.g('", gnm ,"')};");
scopeStatements.push(gnm + " : typeof " + gnm + " === 'undefined' ? undefined : " + gnm);
scopeStatements.push(gnm + " : typeof " + gnm + " === 'undefined' ? n.g('" + gnm + "') : " + gnm);
}
globalsStatement.push(CRLF);
}
Expand Down Expand Up @@ -151,17 +151,21 @@ exports["log"] = function (node, walker) {
* @return {String} a snippet of Javascript code built from the node.
*/
exports["let"] = function (node, walker) {
var expr, index = 1, code = [], assignment = [], varName;
for (var i = 0; i < node.assignments.length; i++) {
expr = formatExpression(node.assignments[i].value, index, walker);
index = expr.nextIndex;
varName = node.assignments[i].identifier;
walker.addScopeVariable(varName);
assignment.push("'" + varName + "'");
assignment.push(expr.exprIdx);
code.push(expr.code);
var expr = formatExpression(node.assignments[0], 1, walker);
var wholeAst = exParser(node.assignments[0].value);
var assignAst, assignmentsAsts = wholeAst instanceof Array ? wholeAst : [wholeAst];

//check if all the assignments are properly constructed
for (var i = 0; i < assignmentsAsts.length; i++) {
assignAst = assignmentsAsts[i];
if (assignAst.a === 'bnr' && assignAst.v === '=') {
walker.addScopeVariable(assignAst.l.v);
} else {
walker.logError("Unsupported expression: " + node.assignments[0].value);
}
}
return ["n.let({", code.join(",") , "},[", assignment.join(',') , "])"].join('');

return ["n.let({", expr.code, "})"].join('');
};

/**
Expand Down
8 changes: 1 addition & 7 deletions hsp/compiler/parser/hspblocks.pegjs
Expand Up @@ -233,7 +233,7 @@ LogBlock
}

LetBlock
= "{" _ "let " _ first:LetAssignment __ next:("," __ LetAssignment)* "}" EOS?
= "{" _ "let " _ first:CoreExpText __ next:("," __ CoreExpText)* "}" EOS?
{
var asn=[first];
if (next) {
Expand All @@ -244,12 +244,6 @@ LetBlock
return {type:"let",assignments:asn, line:line, column:column}
}

LetAssignment
= nm:Identifier _ "=" _ val:HPipeExpression
{
return {identifier:nm, value:val}
}

CoreExpText
= c: (CoreExpTextNoBrackets
/ CoreExpTextInCurly
Expand Down
8 changes: 2 additions & 6 deletions hsp/compiler/treebuilder/syntaxTree.js
Expand Up @@ -269,14 +269,10 @@ var SyntaxTree = klass({
* @return {Integer} the index of the block where the function stopped or -1 if all blocks have been handled.
*/
__let : function (index, blocks, out) {
var node = new Node("let"), block = blocks[index], assignments = [];
var node = new Node("let"), block = blocks[index];
node.line = block.line;
node.column = block.column;
for (var i = 0; i < block.assignments.length; i++) {
var expr = new HExpression(block.assignments[i].value, this);
assignments.push({identifier:block.assignments[i].identifier, value: expr.getSyntaxTree()});
}
node.assignments = assignments ;
node.assignments = block.assignments;
out.push(node);
return index;
},
Expand Down
33 changes: 20 additions & 13 deletions hsp/rt/$let.js
Expand Up @@ -18,21 +18,31 @@
var klass = require("../klass"),
$set = require("../$set"),
doc = require("./document"),
TNode = require("./tnode").TNode;
TNode = require("./tnode").TNode,
exmanipulator = require("../expressions/manipulator");

var LetNode = klass({
$extends : TNode,

/**
* Log node generator ex: {log scope}
* @param {Map<Expression>|int} exps the map of the variables used by the node.
* 0 is passed if no expression is used
* @param {Array} args array of the variable name, expression index associated to this statement
* e.g. ['aVarName',1,'anotherName',2]
* @param {Map<Expression>} expressions that, when evaluated, will create new variables
*/
$constructor : function (exps, args) {
$constructor : function (exps) {
TNode.$constructor.call(this, exps);
this.args = args;
var exp = this.eh.getExpr(1); //there is only one expression for the let block
var trees = exp.isMultiStatement ? exp.ast : [exp.ast];
this.expTrees = [];

/*
* The logic below splits the comma-separated expressions into individual
* expressions and prepares a collection of 2-element arrays where the first
* element is a variable name to be assigned and the second one - expression
* manipulator that knows how to get value of the right-hand side.
*/
for (var i = 0; i < trees.length; i++) {
this.expTrees.push([trees[i].l.v, exmanipulator(exps[0], trees[i].r)]);
}
},

/**
Expand All @@ -56,12 +66,9 @@ var LetNode = klass({
* Process the information to be logged and push it to the log output (browser console by default)
*/
updateScope : function () {
var args=this.args, eh=this.eh, v;
if (args) {
for (var i=0, sz=args.length;sz>i;i+=2) {
v=eh.getValue(args[i+1], this.vscope, undefined);
$set(this.vscope,args[i],v);
}
var expts = this.expTrees;
for (var i = 0; i < expts.length; i++) {
$set(this.vscope, expts[i][0], expts[i][1].getValue(this.vscope, undefined));
}
}
});
Expand Down
68 changes: 14 additions & 54 deletions test/compiler/samples/let1.txt
Expand Up @@ -12,35 +12,12 @@
"type": "let",
"line": 2,
"column": 3,
"assignments": [
{
"identifier": "x",
"value": {
"type": "BinaryExpression",
"operator": "+",
"left": {
"type": "PropertyAccess",
"base": {
"type": "Variable",
"name": "value",
"code": "value"
},
"name": "nbr",
"code": "value.nbr"
},
"right": {
"type": "expression",
"category": "number",
"value": 3,
"code": "3"
},
"category": "jsexpression",
"expType": "BinaryExpression",
"line": 2,
"column": 10
}
}
]
"assignments": [{
category: 'jsexptext',
value: 'x=value.nbr+3',
line: 2,
column: 8
}]
}
]
}
Expand All @@ -53,28 +30,12 @@
"content": [
{
"type": "let",
"assignments": [
{
"identifier": "x",
"value": {
"type": "expression",
"category": "jsexpression",
"objectrefs": [
{
"type": "expression",
"category": "objectref",
"path": [
"value",
"nbr"
]
}
],
"code": "(a0 + 3)",
"line": 2,
"column": 10
}
}
]
"assignments": [{
category: 'jsexptext',
value: 'x=value.nbr+3',
line: 2,
column: 8
}]
}
]
}
Expand All @@ -83,7 +44,6 @@
##### Template Code
test=[__s,
n.let({
e1:[6,function(a0) {return (a0 + 3);},2],
e2:[1,2,"value","nbr"]
},['x',1])
e1:[9,"x=value.nbr+3"]
})
]
6 changes: 2 additions & 4 deletions test/compiler/samples/let2.txt
Expand Up @@ -22,10 +22,8 @@ test=[__s,
[
n.$text(0,[" "]),
n.let({
e1:[1,2,"value","nbr"],
e2:[2,1,_blah]
},['aVarName',1,'anotherName',2]
)
e1:[9,"aVarName = value.nbr, anotherName = blah"]
})
],
1
)
Expand Down
7 changes: 2 additions & 5 deletions test/compiler/samples/let3.txt
Expand Up @@ -18,11 +18,8 @@ test=[__s,
"div",0,{"class":"foo"},0,[
n.$text(0,[" "]),
n.let({
e1:[6,function(a0) {return new a0();},2],
e2:[2,1,_Foo],
e3:[6,function(a0) {return new a0();},4],
e4:[1,2,"foo","Bar"]
},['aVarName',1,'anotherName',3])
e1:[9,"aVarName = new Foo(), anotherName = new foo.Bar()"]
})
],1
)
]
8 changes: 2 additions & 6 deletions test/compiler/samples/let4.txt
Expand Up @@ -16,12 +16,8 @@ test=[__s,
n.elt(
"div",0,{"class":"foo"},0,[
n.let({
e1:[6,function(a0,a1) {return new a0("a",123,a1);},2,3],
e2:[2,1,_Foo],
e3:[4,1,_blah,1,4],
e4:[6,function(a0) {return (1 + a0);},5],
e5:[1,2,"foo","value"]
},['val',1])
e1:[9,"val = new Foo(\"a\",123,blah(1+foo.value))"]
})
],
1
)
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/tests.js
Expand Up @@ -274,7 +274,7 @@ describe('Block Parser: ', function () {
'',
'var test = require("hsp/rt").template([], function(n){',
' var _body,_panel;try {_body=body} catch(e) {_body=n.g(\'body\')};try {_panel=panel} catch(e) {_panel=n.g(\'panel\')};',
' var __s = {body : typeof body === \'undefined\' ? undefined : body, panel : typeof panel === \'undefined\' ? undefined : panel};',
' var __s = {body : typeof body === \'undefined\' ? n.g(\'body\') : body, panel : typeof panel === \'undefined\' ? n.g(\'panel\') : panel};',
' return [__s,',
' n.cpt([_panel,"panel"],0,0,0,[n.cpt([_body,"body"],0,{"class":"foo"},0,[n.$text(0,["Hello World! "])])])];',
'});'
Expand Down

0 comments on commit 5facfb4

Please sign in to comment.