|
|
|
@ -1,7 +1,6 @@
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
let objects = require("../../utils/objects"),
|
|
|
|
|
asts = require("../asts"),
|
|
|
|
|
let asts = require("../asts"),
|
|
|
|
|
visitor = require("../visitor"),
|
|
|
|
|
op = require("../opcodes"),
|
|
|
|
|
js = require("../js");
|
|
|
|
@ -204,6 +203,16 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function cloneEnv(env) {
|
|
|
|
|
let clone = {};
|
|
|
|
|
|
|
|
|
|
Object.keys(env).forEach(name => {
|
|
|
|
|
clone[name] = env[name];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return clone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildSequence() {
|
|
|
|
|
return Array.prototype.concat.apply([], arguments);
|
|
|
|
|
}
|
|
|
|
@ -221,7 +230,7 @@ function generateBytecode(ast) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildCall(functionIndex, delta, env, sp) {
|
|
|
|
|
let params = objects.values(env).map(p => sp - p);
|
|
|
|
|
let params = Object.keys(env).map(name => sp - env[name]);
|
|
|
|
|
|
|
|
|
|
return [op.CALL, functionIndex, delta, params.length].concat(params);
|
|
|
|
|
}
|
|
|
|
@ -232,7 +241,7 @@ function generateBytecode(ast) {
|
|
|
|
|
[op.SILENT_FAILS_ON],
|
|
|
|
|
generate(expression, {
|
|
|
|
|
sp: context.sp + 1,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
}),
|
|
|
|
|
[op.SILENT_FAILS_OFF],
|
|
|
|
@ -318,7 +327,7 @@ function generateBytecode(ast) {
|
|
|
|
|
return buildSequence(
|
|
|
|
|
generate(alternatives[0], {
|
|
|
|
|
sp: context.sp,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
}),
|
|
|
|
|
alternatives.length > 1
|
|
|
|
@ -338,7 +347,7 @@ function generateBytecode(ast) {
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
action: function(node, context) {
|
|
|
|
|
let env = objects.clone(context.env),
|
|
|
|
|
let env = cloneEnv(context.env),
|
|
|
|
|
emitCall = node.expression.type !== "sequence"
|
|
|
|
|
|| node.expression.elements.length === 0,
|
|
|
|
|
expressionCode = generate(node.expression, {
|
|
|
|
@ -424,7 +433,7 @@ function generateBytecode(ast) {
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
labeled: function(node, context) {
|
|
|
|
|
let env = objects.clone(context.env);
|
|
|
|
|
let env = cloneEnv(context.env);
|
|
|
|
|
|
|
|
|
|
context.env[node.label] = context.sp + 1;
|
|
|
|
|
|
|
|
|
@ -440,7 +449,7 @@ function generateBytecode(ast) {
|
|
|
|
|
[op.PUSH_CURR_POS],
|
|
|
|
|
generate(node.expression, {
|
|
|
|
|
sp: context.sp + 1,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
}),
|
|
|
|
|
buildCondition(
|
|
|
|
@ -463,7 +472,7 @@ function generateBytecode(ast) {
|
|
|
|
|
return buildSequence(
|
|
|
|
|
generate(node.expression, {
|
|
|
|
|
sp: context.sp,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
}),
|
|
|
|
|
buildCondition(
|
|
|
|
@ -477,7 +486,7 @@ function generateBytecode(ast) {
|
|
|
|
|
zero_or_more: function(node, context) {
|
|
|
|
|
let expressionCode = generate(node.expression, {
|
|
|
|
|
sp: context.sp + 1,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -492,7 +501,7 @@ function generateBytecode(ast) {
|
|
|
|
|
one_or_more: function(node, context) {
|
|
|
|
|
let expressionCode = generate(node.expression, {
|
|
|
|
|
sp: context.sp + 1,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -510,7 +519,7 @@ function generateBytecode(ast) {
|
|
|
|
|
group: function(node, context) {
|
|
|
|
|
return generate(node.expression, {
|
|
|
|
|
sp: context.sp,
|
|
|
|
|
env: objects.clone(context.env),
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
|
action: null
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|