✨ code to enter and return from scope
This commit is contained in:
parent
10eca29f76
commit
72454d3538
202
src/runner.js
202
src/runner.js
@ -16,12 +16,10 @@ class Juicescript_runner {
|
|||||||
*/
|
*/
|
||||||
run(){
|
run(){
|
||||||
// RESET //
|
// RESET //
|
||||||
// command counter
|
// stack for command counter, scope and variable list
|
||||||
this.counter = 0;
|
|
||||||
|
|
||||||
// scope and variable stack
|
|
||||||
this.stack = [{
|
this.stack = [{
|
||||||
scope: null,
|
scope: null,
|
||||||
|
counter: 0,
|
||||||
variable: {}
|
variable: {}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@ -70,8 +68,7 @@ class Juicescript_runner {
|
|||||||
|
|
||||||
// TRY AS USER-DEFINED COMMAND //
|
// TRY AS USER-DEFINED COMMAND //
|
||||||
if(Object.keys(this.tree.scope).includes(this.command.name)){
|
if(Object.keys(this.tree.scope).includes(this.command.name)){
|
||||||
//*/ TODO: enter scope
|
this.scope_enter();
|
||||||
/**/this.error("user-defined: " + this.command.name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,9 +92,10 @@ class Juicescript_runner {
|
|||||||
// IN USER-DEFINED SCOPE //
|
// IN USER-DEFINED SCOPE //
|
||||||
if(this.scope !== null){
|
if(this.scope !== null){
|
||||||
// return from scope
|
// return from scope
|
||||||
//*/ TODO: return from scope
|
this.scope_return();
|
||||||
/**/this.error("return from scope");
|
|
||||||
return false;
|
// check again for new scope
|
||||||
|
return this.handle_command_list_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -112,12 +110,122 @@ class Juicescript_runner {
|
|||||||
this.command = this.scope_tree.command[this.counter];
|
this.command = this.scope_tree.command[this.counter];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
HELPER: Handle entering another scope by user command
|
||||||
|
*/
|
||||||
|
scope_enter(){
|
||||||
|
// VALIDATE ARGUMENTS //
|
||||||
|
// argument count
|
||||||
|
this.argument_validate_count(this.tree.scope[this.command.name].parameter_count);
|
||||||
|
|
||||||
|
// they must all be of type 'value'
|
||||||
|
for(var q = 1; q <= this.command.argument.length; q++){
|
||||||
|
this.argument_validate_type(q, Juicescript.argument_type.VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RESOLVE ARGUMENTS //
|
||||||
|
// resolve to value
|
||||||
|
let argument_value_list = [];
|
||||||
|
for(var q = 1; q <= this.command.argument.length; q++){
|
||||||
|
argument_value_list.push(this.argument_value(q));
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve to absolute variable
|
||||||
|
let argument_variable_list = [];
|
||||||
|
for(var q = 0; q < this.command.argument.length; q++){
|
||||||
|
if(this.command.argument[q].type === Juicescript.argument_type.VARIABLE){
|
||||||
|
// variable, add absolute variable
|
||||||
|
argument_variable_list.push(this.argument_variable(q + 1));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// literal, add null
|
||||||
|
argument_variable_list.push(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PUSH NEW LAYER TO STACK //
|
||||||
|
this.stack.push({
|
||||||
|
scope: this.command.name,
|
||||||
|
counter: 0,
|
||||||
|
variable: {},
|
||||||
|
argument_variable: argument_variable_list
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// FILL IN PARAMETER VARIABLES //
|
||||||
|
for(var q = 0; q < this.scope_tree.parameter.length; q++){
|
||||||
|
// get parameter name
|
||||||
|
let parameter_name = this.scope_tree.parameter[q].name;
|
||||||
|
|
||||||
|
// get argument value
|
||||||
|
let argument_value = argument_value_list[q];
|
||||||
|
|
||||||
|
// store as variable in current scope
|
||||||
|
this.variable_set({
|
||||||
|
name: parameter_name,
|
||||||
|
index: []
|
||||||
|
}, argument_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GETTER: Return name of current scope (top of stack)
|
HELPER: Handle returning back to previous scope
|
||||||
|
*/
|
||||||
|
scope_return(){
|
||||||
|
// REMEMBER VALUES TO TAKE OVER //
|
||||||
|
let take_over_list = [];
|
||||||
|
for(var q = 0; q < this.scope_tree.parameter.length; q++){
|
||||||
|
// make sure argument was set when called
|
||||||
|
if(q >= this.stack_top.argument_variable.length) continue;
|
||||||
|
|
||||||
|
// make sure parameter is read-write
|
||||||
|
if(!this.scope_tree.parameter[q].reference) continue;
|
||||||
|
|
||||||
|
// make sure the argument was a variable
|
||||||
|
if(this.stack_top.argument_variable[q] === null) continue;
|
||||||
|
|
||||||
|
// get parameter name
|
||||||
|
let parameter_name = this.scope_tree.parameter[q].name;
|
||||||
|
|
||||||
|
// get variable's final value
|
||||||
|
let variable_value = this.variable_get({
|
||||||
|
name: parameter_name,
|
||||||
|
index: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// add to list
|
||||||
|
take_over_list.push({variable: this.stack_top.argument_variable[q], value: variable_value});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// POP LAYER FROM STACK //
|
||||||
|
this.stack.pop();
|
||||||
|
|
||||||
|
|
||||||
|
// TAKE OVER READ-WRITE PARAMETERS //
|
||||||
|
for(var one_reference of take_over_list){
|
||||||
|
// set variable's new value
|
||||||
|
this.variable_set(one_reference.variable, one_reference.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GETTER: Return top/bottom of stack
|
||||||
|
*/
|
||||||
|
get stack_top(){
|
||||||
|
return this.stack[this.stack.length - 1];
|
||||||
|
}
|
||||||
|
get stack_bottom(){
|
||||||
|
return this.stack[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GETTER: Return name of current scope
|
||||||
*/
|
*/
|
||||||
get scope(){
|
get scope(){
|
||||||
return this.stack[this.stack.length - 1].scope;
|
return this.stack_top.scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -139,6 +247,16 @@ class Juicescript_runner {
|
|||||||
return this.tree.scope[this.scope];
|
return this.tree.scope[this.scope];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GETTER / SETTER: Return current command counter
|
||||||
|
*/
|
||||||
|
get counter(){
|
||||||
|
return this.stack_top.counter;
|
||||||
|
}
|
||||||
|
set counter(value){
|
||||||
|
this.stack_top.counter = value;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
COMMAND HELPER: Validate number of command arguments
|
COMMAND HELPER: Validate number of command arguments
|
||||||
*/
|
*/
|
||||||
@ -219,9 +337,9 @@ class Juicescript_runner {
|
|||||||
*/
|
*/
|
||||||
argument(number){
|
argument(number){
|
||||||
// GET WANTED ARGUMENT //
|
// GET WANTED ARGUMENT //
|
||||||
// make sure this argument number exists
|
// fallback for argument not existing
|
||||||
if(this.command.argument.length < number){
|
if(this.command.argument.length < number){
|
||||||
throw "unable to extract value of argument " + number + ", command " + this.command.name + " (not defined)";
|
return {type: Juicescript.argument_type.LITERAL, value: null};
|
||||||
}
|
}
|
||||||
|
|
||||||
// get argument object
|
// get argument object
|
||||||
@ -318,17 +436,15 @@ class Juicescript_runner {
|
|||||||
*/
|
*/
|
||||||
variable_get(variable){
|
variable_get(variable){
|
||||||
// FIND VARIABLE IN STACK //
|
// FIND VARIABLE IN STACK //
|
||||||
// check if global
|
// get its scope's full variable list
|
||||||
/**/let is_global = false;
|
let variable_list;
|
||||||
|
if(this.variable_is_global(variable)){
|
||||||
|
variable_list = this.stack_bottom.variable;
|
||||||
|
} else {
|
||||||
|
variable_list = this.stack_top.variable;
|
||||||
|
}
|
||||||
|
|
||||||
// get index on stack
|
// try to load value from list
|
||||||
let stack_index = this.stack.length - 1;
|
|
||||||
if(is_global) stack_index = 0;
|
|
||||||
|
|
||||||
// get index' full variable list
|
|
||||||
let variable_list = this.stack[stack_index].variable;
|
|
||||||
|
|
||||||
// try to load value from stack
|
|
||||||
let value = null;
|
let value = null;
|
||||||
if(Object.keys(variable_list).includes(variable.name)){
|
if(Object.keys(variable_list).includes(variable.name)){
|
||||||
value = variable_list[variable.name];
|
value = variable_list[variable.name];
|
||||||
@ -336,7 +452,9 @@ class Juicescript_runner {
|
|||||||
|
|
||||||
|
|
||||||
// APPLY INDEXES //
|
// APPLY INDEXES //
|
||||||
|
//*/ TODO: apply indexes
|
||||||
/**/if(variable.index.length > 0) this.warning("yet to be implemented");
|
/**/if(variable.index.length > 0) this.warning("yet to be implemented");
|
||||||
|
/**/if(value === undefined) value = null;
|
||||||
|
|
||||||
|
|
||||||
// RETURN VALUE //
|
// RETURN VALUE //
|
||||||
@ -384,20 +502,38 @@ class Juicescript_runner {
|
|||||||
*/
|
*/
|
||||||
variable_set(variable, value){
|
variable_set(variable, value){
|
||||||
// FIND VARIABLE IN STACK //
|
// FIND VARIABLE IN STACK //
|
||||||
// check if global
|
// get its scope's full variable list
|
||||||
/**/let is_global = false;
|
let variable_list;
|
||||||
|
if(this.variable_is_global(variable)){
|
||||||
|
variable_list = this.stack_bottom.variable;
|
||||||
|
} else {
|
||||||
|
variable_list = this.stack_top.variable;
|
||||||
|
}
|
||||||
|
|
||||||
// get index on stack
|
// set value on list
|
||||||
let stack_index = this.stack.length - 1;
|
//*/ TODO: apply indexes
|
||||||
if(is_global) stack_index = 0;
|
|
||||||
|
|
||||||
// get index' full variable list
|
|
||||||
let variable_list = this.stack[stack_index].variable;
|
|
||||||
|
|
||||||
// set value on stack
|
|
||||||
variable_list[variable.name] = value;
|
variable_list[variable.name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
VARIABLE HELPER: Check if variable is global
|
||||||
|
*/
|
||||||
|
variable_is_global(variable){
|
||||||
|
// CHECK IF IN ROOT SCOPE //
|
||||||
|
if(this.scope === null){
|
||||||
|
// can't be global in here
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// CHECK IF IN LIST OF GLOBAL VARIABLE NAMES //
|
||||||
|
// get list
|
||||||
|
let global_list = this.scope_tree.global;
|
||||||
|
|
||||||
|
// check
|
||||||
|
return global_list.includes(variable.name);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GETTER: Check if there was a warning/error so far
|
GETTER: Check if there was a warning/error so far
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user