mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Add operator overloading through JS AST parsing and mangling to PaperScript.
This commit is contained in:
parent
111fd5ea14
commit
15a7b7e245
1 changed files with 110 additions and 3 deletions
|
@ -1,8 +1,115 @@
|
|||
var PaperScript = new function() {
|
||||
|
||||
// Handle Math Operators
|
||||
|
||||
var operators = {
|
||||
'+': 'add',
|
||||
'-': 'subtract',
|
||||
'*': 'multiply',
|
||||
'/': 'divide',
|
||||
'%': 'modulo',
|
||||
'==': 'equals',
|
||||
'!=': 'equals'
|
||||
};
|
||||
|
||||
paper.handleOperator = function(operator, left, right) {
|
||||
var handler = operators[operator];
|
||||
if (left && left[handler]) {
|
||||
var res = left[handler](right);
|
||||
return operator == '!=' ? !res : res;
|
||||
}
|
||||
switch (operator) {
|
||||
case '+': return left + right;
|
||||
case '-': return left - right;
|
||||
case '*': return left * right;
|
||||
case '/': return left / right;
|
||||
case '%': return left % right;
|
||||
case '==': return left == right;
|
||||
case '!=': return left != right;
|
||||
default:
|
||||
throw new Error('Implement Operator: ' + operator);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle Sign Operators
|
||||
|
||||
var signOperator = {
|
||||
'-': 'negate'
|
||||
};
|
||||
|
||||
paper.handleSignOperator = function(operator, exp) {
|
||||
var handler = signOperator[operator];
|
||||
if (exp && exp[handler]) {
|
||||
return exp[handler]();
|
||||
}
|
||||
switch (operator) {
|
||||
case '+': return +exp;
|
||||
case '-': return -exp;
|
||||
default:
|
||||
throw new Error('Implement Sign Operator: ' + operator);
|
||||
}
|
||||
}
|
||||
|
||||
// AST Helpers
|
||||
|
||||
function isDynamic(exp) {
|
||||
var type = exp[0];
|
||||
return type != 'num' && type != 'string';
|
||||
}
|
||||
|
||||
function handleOperator(operator, left, right) {
|
||||
// Only replace operators with calls to paper.handleOperator if
|
||||
// the left hand side is potentially an object.
|
||||
if (operators[operator] && isDynamic(left)) {
|
||||
// Replace with paper.handleOperator(operator, left, right):
|
||||
return ['call', ['dot', ['name', 'paper'], 'handleOperator'],
|
||||
[['string', operator], left, right]];
|
||||
}
|
||||
}
|
||||
|
||||
function compile(code) {
|
||||
// TODO: Parse code and replace math operators with calls to methods
|
||||
// that handle overloading.
|
||||
return code;
|
||||
// Use parse-js to translate the code into a AST structure which is then
|
||||
// walked and parsed for operators to overload. The resulting AST is
|
||||
// translated back to code and evaluated.
|
||||
var ast = parse_js.parse(code),
|
||||
walker = parse_js.walker(),
|
||||
walk = walker.walk;
|
||||
|
||||
ast = walker.with_walkers({
|
||||
'binary': function(operator, left, right) {
|
||||
// Handle simple mathematical operators here:
|
||||
return handleOperator(operator, left = walk(left),
|
||||
right = walk(right))
|
||||
// Always return something since we're walking left and
|
||||
// right for the handleOperator() call already.
|
||||
|| [this[0], operator, left, right];
|
||||
},
|
||||
|
||||
'assign': function(operator, left, right) {
|
||||
// Handle assignments like +=, -=, etc:
|
||||
// Check if the assignment operator needs to be handled by paper
|
||||
// if so, convert the assignment to a simple = and use result of
|
||||
// of handleOperator on the right hand side.
|
||||
var res = handleOperator(operator, left = walk(left),
|
||||
right = walk(right));
|
||||
if (res)
|
||||
return [this[0], true, left, res];
|
||||
// Always return something for the same reason as in binary
|
||||
return [this[0], operator, left, right];
|
||||
},
|
||||
|
||||
'unary-prefix': function(operator, exp) {
|
||||
if (signOperator[operator] && isDynamic(exp)) {
|
||||
return ['call', ['dot', ['name', 'paper'],
|
||||
'handleSignOperator'],
|
||||
[['string', operator], walk(exp)]];
|
||||
}
|
||||
}
|
||||
}, function() {
|
||||
return walk(ast);
|
||||
});
|
||||
|
||||
return parse_js.stringify(ast);
|
||||
}
|
||||
|
||||
function run(code) {
|
||||
|
|
Loading…
Reference in a new issue