Skip to content

Commit

Permalink
Renamed symbolTable to runtime. Implemented 'return' keyword function…
Browse files Browse the repository at this point in the history
…ality.
  • Loading branch information
luizfar committed Apr 23, 2011
1 parent 8725c59 commit 6e006e0
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 99 deletions.
16 changes: 11 additions & 5 deletions runner.html
Expand Up @@ -2,9 +2,9 @@
<head>
<script src="lib/jquery.min.js"></script>
<script src="src/bootstrap.js"></script>
<script src="src/runtime.js"></script>
<script src="src/util.js"></script>
<script src="src/symbol.js"></script>
<script src="src/symbolTable.js"></script>
<script src="src/lexer.js"></script>
<script src="src/functionParser.js"></script>
<script src="src/classParser.js"></script>
Expand All @@ -15,11 +15,17 @@
<script src="src/jazz.js"></script>

<script type="jazz">
x = 2
if x is 3
log "=="
log "done"
f = (param) {
if param
return "param is true"
else
return "param is false"
log "not here"
}
log f(true)
log f(false)
</script>

x = 1 + 1
y = x * 2 - 3 * 2
log "-3 : " + y.add(-4).add(5).multiply(3)
Expand Down
2 changes: 1 addition & 1 deletion spec/SpecRunner.html
Expand Up @@ -10,9 +10,9 @@
<!-- include source files here... -->
<script src="../lib/jquery.min.js"></script>
<script src="../src/bootstrap.js"></script>
<script src="../src/runtime.js"></script>
<script src="../src/util.js"></script>
<script src="../src/symbol.js"></script>
<script src="../src/symbolTable.js"></script>
<script src="../src/lexer.js"></script>
<script src="../src/functionParser.js"></script>
<script src="../src/classParser.js"></script>
Expand Down
14 changes: 14 additions & 0 deletions spec/jazz.function.spec.js
Expand Up @@ -33,5 +33,19 @@ describe("Jazz interpreter for Object's methods", function () {
'f("hey")("you")');
expect(console.content).toEqual("hey\nyou");
});

it("should return from a function when a return statement is executed", function () {
jazz.execute(
'f = (param) {\n' +
' if param\n' +
' return "param is true"\n' +
' else\n' +
' return "param is false"\n' +
' log "not here"\n' +
'}\n' +
'log f(true)\n' +
'log f(false)');
expect(console.content).toEqual("param is true\nparam is false");
});

});
4 changes: 2 additions & 2 deletions src/classParser.js
@@ -1,6 +1,6 @@
var jazz = jazz || {};

jazz.ClassParser = function (lexer, symbolTable, functionParser, exprParser) {
jazz.ClassParser = function (lexer, runtime, functionParser, exprParser) {
var util = jazz.util;
var symbol = jazz.symbol;

Expand All @@ -16,7 +16,7 @@ jazz.ClassParser = function (lexer, symbolTable, functionParser, exprParser) {
}
lexer.checkAndConsumeToken(symbol.RIGHT_CUR);
return function () {
symbolTable.addClass(clazz);
runtime.addClass(clazz);
}
};
}
25 changes: 19 additions & 6 deletions src/expressionParser.js
@@ -1,9 +1,9 @@
var jazz = jazz || {};

jazz.ExpressionParser = function (lexer, symbolTable) {
var functionParser = new jazz.FunctionParser(lexer, symbolTable, this);
var classParser = new jazz.ClassParser(lexer, symbolTable, functionParser, this);
var objectParser = new jazz.ObjectParser(lexer, symbolTable, this);
jazz.ExpressionParser = function (lexer, runtime) {
var functionParser = new jazz.FunctionParser(lexer, runtime, this);
var classParser = new jazz.ClassParser(lexer, runtime, functionParser, this);
var objectParser = new jazz.ObjectParser(lexer, runtime, this);

var symbol = jazz.symbol;
var operations = jazz.operations;
Expand Down Expand Up @@ -67,6 +67,9 @@ jazz.ExpressionParser = function (lexer, symbolTable) {
case symbol.IF:
return parseIf();

case symbol.RETURN:
return parseReturn();

case symbol.CLASS:
return classParser.parseClass();

Expand Down Expand Up @@ -97,6 +100,16 @@ jazz.ExpressionParser = function (lexer, symbolTable) {
};
}

function parseReturn () {
lexer.next();
var expression = parseExpression();
return function () {
var returnValue = expression();
runtime.clearExpressions();
return returnValue;
};
}

function parseAlert() {
lexer.next();
var expression = parseOrExpression();
Expand Down Expand Up @@ -263,12 +276,12 @@ jazz.ExpressionParser = function (lexer, symbolTable) {
lexer.next();
var expression = parseExpression();
return function () {
var variable = symbolTable.getOrCreate(variableName);
var variable = runtime.getOrCreate(variableName);
variable.value = expression();
};
}
return function () {
var variable = symbolTable.get(variableName);
var variable = runtime.get(variableName);
return variable.value;
};
}
Expand Down
23 changes: 13 additions & 10 deletions src/functionParser.js
@@ -1,6 +1,6 @@
var jazz = jazz || {};

jazz.FunctionParser = function (lexer, symbolTable, expressionParser) {
jazz.FunctionParser = function (lexer, runtime, expressionParser) {
var util = jazz.util;
var symbol = jazz.symbol;

Expand Down Expand Up @@ -43,19 +43,22 @@ jazz.FunctionParser = function (lexer, symbolTable, expressionParser) {
}
lexer.next();
_function.invoke = function (receiver, args) {
symbolTable.addScope();
runtime.addContext();
util.each(_function.params, function (param, index) {
symbolTable.add({
runtime.add({
name: param,
value: typeof args[index] !== "undefined" ? args[index] : jazz.lang.Null.init()
value: typeof args[index] !== "undefined" ? args[index] : jazz.lang.Null.NULL_OBJECT
});
});
var lastValue = jazz.lang.Null.init();
util.each(this.expressions, function (expression) {
lastValue = expression();
});
symbolTable.removeScope();
return lastValue;
var returnValue = jazz.lang.Null.NULL_OBJECT;
runtime.setExpressions(_function.expressions);
var expression = runtime.removeExpression();
while (expression) {
returnValue = expression();
expression = runtime.removeExpression();
}
runtime.removeContext();
return returnValue;
}
return _function;
}
Expand Down
6 changes: 3 additions & 3 deletions src/interpreter.js
Expand Up @@ -3,10 +3,10 @@ var jazz = jazz || {};
jazz.Interpreter = function (input) {

var lexer = new jazz.Lexer(input);
var symbolTable = new jazz.SymbolTable();
var parser = new jazz.Parser(lexer, symbolTable);
var runtime = new jazz.Runtime();
var parser = new jazz.Parser(lexer, runtime);

symbolTable.addClass(jazz.lang.Class);
runtime.addClass(jazz.lang.Class);

this.start = function () {
lexer.next();
Expand Down
2 changes: 1 addition & 1 deletion src/objectParser.js
@@ -1,6 +1,6 @@
var jazz = jazz || {};

jazz.ObjectParser = function (lexer, symbolTable, expressionParser) {
jazz.ObjectParser = function (lexer, runtime, expressionParser) {
var util = jazz.util;
var symbol = jazz.symbol;

Expand Down
4 changes: 2 additions & 2 deletions src/parser.js
@@ -1,7 +1,7 @@
var jazz = jazz || {};

jazz.Parser = function (lexer, symbolTable) {
var exprParser = new jazz.ExpressionParser(lexer, symbolTable);
jazz.Parser = function (lexer, runtime) {
var exprParser = new jazz.ExpressionParser(lexer, runtime);

this.start = function () {
do {
Expand Down
75 changes: 75 additions & 0 deletions src/runtime.js
@@ -0,0 +1,75 @@
var jazz = jazz || {};

jazz.Runtime = function () {
var contexts = [];
var contextIndex = 0;
var currentContext = emptyContext();

contexts[contextIndex] = currentContext;

function emptyContext() {
return {
variables: {},
expressions: [],
exprIndex: undefined
};
}

this.addClass = function(clazz) {
this.add({
type: jazz.lang.Class,
value: clazz,
name: clazz.name
});
};

this.add = function (variable) {
if (currentContext.variables[variable.name]) {
jazz.util.error("Identifier '" + variable.name + "' already in use.");
} else {
currentContext.variables[variable.name] = variable;
}
};

this.getOrCreate = function (variableName) {
var variable = currentContext.variables[variableName];
if (!variable) {
variable = { name: variableName, value: jazz.lang.Null.init() };
currentContext.variables[variableName] = variable;
}
return variable;
}

this.get = function (identifier) {
for (var i = contextIndex; i >= 0; --i) {
var variable = contexts[i].variables[identifier];
if (variable) {
return variable;
}
}
jazz.util.error("Unknown identifier: " + identifier);
};

this.setExpressions = function (expressions) {
currentContext.expressions = expressions;
currentContext.exprIndex = 0;
};

this.removeExpression = function () {
return currentContext.expressions[currentContext.exprIndex++];
};

this.clearExpressions = function () {
currentContext.exprIndex = currentContext.expressions.length;
}

this.addContext = function () {
currentContext = emptyContext();
contexts[++contextIndex] = currentContext;
};

this.removeContext = function () {
currentContext = contexts[--contextIndex];
delete contexts[contextIndex + 1];
};
}
3 changes: 2 additions & 1 deletion src/symbol.js
Expand Up @@ -29,7 +29,8 @@ jazz.symbol = {
LOG: "log",
OR: "or",
TRUE: "true",
FALSE: "false"
FALSE: "false",
RETURN: "return"
};

(function () {
Expand Down
68 changes: 0 additions & 68 deletions src/symbolTable.js

This file was deleted.

0 comments on commit 6e006e0

Please sign in to comment.