/*====================================================
* rapl_script.js "A Tcl like language implementation in Javascript named WebRAPL
* (Web Rapid Application Programming Language)"
*
* RAPL script implementation
*
* Released under BSD license.
* (BSD license found at <http://www.tcl.tk/software/tcltk/license.html>)
*
* Arnulf Wiedemann 2011
*/
RP.add("rapl-script", function(R, name) {
function RaplScript(interp) {
R.log('constructor called', '2.life', 'RaplScript', true);
// kweight
var script = this;
var constructor = script.constructor;
RaplScript.superclass.constructor.apply(script, arguments);
R.Base.script_oid++;
script.oid = R.Base.script_oid;
script.my_name = "RaplScript";
script.interp = interp;
script.token_list = null;
script.result = null;
script.script_token_idx = null;
script.token_idx = null;
script.text = null;
script.text_len = null;
script.script_object = {
len: null, /* Length as number of tokens. */
tokens: null, /* Tokens array. */
subst_flags: null, /* flags used for the compilation of "subst" objects */
in_use: null, /* Used to share a ScriptObj. Currently
only used by evalObj() as protection against
shimmering of the currently evaluated object. */
file_name_obj: null,
line: null /* Line number of the first line */
};
R.log('constructor end', '2.life', 'RaplScript', true);
}
R.extend(RaplScript, R.RaplObject, {
/* ==================== TOKEN_IS_SEP ================================== */
TOKEN_IS_SEP: function(token) {
var script = this;
return (token >= script.TOKEN_WORD_SEP && token <= script.TOKEN_EOF);
},
/* ==================== scriptTokenListInit ================================== */
scriptTokenListInit: function() {
var script = this;
script.token_list = new Array();
},
/* ==================== scriptTokenListFree ================================== */
scriptTokenListFree: function() {
var script = this;
script.token_list = null;
},
/* ==================== scriptAddToken ================================== */
scriptAddToken: function(start, len, token, line) {
var script = this;
//var str = script.text.substring(start, start +len);
//print("Add!"+start+"!"+len+"!"+script.getTokenString(token)+"!"+line+"!str!"+str+"!");
var token_info = {
start: start,
len: len,
token: token,
line: line
};
//print("To!"+script.getTokenString(token_info.token)+"!"+token_info.start+"!");
script.token_list.push(token_info);
},
/* ==================== scriptObjAddTokens ================================== */
/**
* Takes a tokenlist and creates the allocated list of script tokens
* in script.script_object.tokens, of length script.script_object.len.
*
* Unnecessary tokens are discarded, and LINE and WORD tokens are inserted
* as required.
*
* Also sets script.script_object.line to the line number of the first token
*/
scriptObjAddTokens: function() {
var script = this;
var line_args = 0; /* Number of tokens so far for the current command */
var line_first_idx; /* This is the first token for the current command */
var count;
var line_no;
var debug_script_tokens = 1;
var token_list_info;
var token_info;
if (debug_script_tokens) {
print("======== Tokens ======");
for (var i = 0; i < script.token_list.length; i++) {
token_list_info = script.token_list[i];
print("["+i+"]@"+token_list_info.line+" "+script.getTokenString(token_list_info.token)+" '"+script.text.substring(token_list_info.start, token_list_info.start + token_list_info.len)+"'");
}
print("======== Tokens END ======");
}
/* May need up to one extra script token for each EOL in the worst case */
count = script.token_list.length;
for (var i = 0; i < script.token_list.length; i++) {
token_list_info = script.token_list[i];
if (token_list_info.token == script.TOKEN_EOL) {
count++;
}
}
line_no = script.token_list[0].line;
script.script_object.line = line_no;
script.script_object.tokens = new Array();
for (var i = 0; i < count; i++) {
token_info = {
token: null,
obj_ptr: null
};
script.script_object.tokens.push(token_info);
}
script.token_idx = 0;
/* This is the first token for the current command */
script.script_token_idx = 0;
line_first_idx = script.token_idx;
script.token_idx++;
while (script.script_token_idx < script.token_list.length) {
/* Look ahead to find out how many tokens make up the next word */
var word_tokens;
token_list_info = script.token_list[script.script_token_idx];
print("11["+script.script_token_idx+"]@"+token_list_info.line+" "+script.getTokenString(token_list_info.token)+" '"+script.text.substring(token_list_info.start, (token_list_info.start + token_list_info.len))+"'");
/* Skip any leading separators */
while (token_list_info.token == script.TOKEN_WORD_SEP) {
script.script_token_idx++;
token_list_info = script.token_list[script.script_token_idx];
}
word_tokens = script.countWordTokens(script.script_token_idx);
if (word_tokens == 0) {
/* None, so at end of line */
if (line_args) {
var my_token_info = script.script_object.tokens[line_first_idx];
my_token_info.token = script.TOKEN_LINE;
my_token_info.obj_ptr = script.interp.script_line_obj_type.newScriptLineObject(line_args, line_no);
my_token_info.obj_ptr.incrRefCount(my_token_info.obj_ptr);
/* Reset for new line */
line_args = 0;
line_first_idx = script.token_idx;
script.token_idx++;
}
script.script_token_idx++;
continue;
} else {
if (word_tokens != 1) {
/* More than 1, or {expand}, so insert a WORD token */
token_info = script.script_object.tokens[script.token_idx];
token_info.token = script.TOKEN_WORD;
token_info.obj_ptr = script.interp.int_obj_type.newIntObj(word_tokens);
token_info.obj_ptr.incrRefCount(token_info.obj_ptr);
script.token_idx++;
if (word_tokens < 0) {
/* Skip the expand token */
script.script_token_idx++;
token_list_info = script.token_list[script.script_token_idx];
word_tokens = -word_tokens - 1;
line_args--;
}
}
if (line_args == 0) {
/* First real token on the line, so record the line number */
line_no = script.token_list[script.script_token_idx].line;
}
line_args++;
/* Add each non-separator word token to the line */
while (word_tokens--) {
token_list_info = script.token_list[script.script_token_idx];
token_info = script.script_object.tokens[script.token_idx];
token_info.token = token_list_info.token;
token_info.obj_ptr = script.interp.script_obj_type.makeScriptObject(script);
token_info.obj_ptr.incrRefCount(token_info.obj_ptr);
script.script_token_idx++;
/* Every object is initially a string, but the
* internal type may be specialized during execution of the
* script. */
script.interp.source_obj_type.setSourceInfo(token_info.obj_ptr, script.script_object.file_name_obj, token_list_info.line);
script.token_idx++;
}
}
}
if (line_args == 0) {
script.token_idx--;
token_info = script.script_object.tokens[script.token_idx];
}
script.len = script.token_idx;
if (debug_script_tokens) {
print("scriptObjAddTokens!"+script.script_object.file_name_obj+"!");
var fname = script.interp.string_obj_type.getString(script.script_object.file_name_obj);
print("======== Script ("+fname+") ======");
for (var i = 0; i < script.token_idx; i++) {
var token_info = script.script_object.tokens[i];
print("["+i+"]@"+script.getTokenString(token_info.token)+"!"+script.interp.string_obj_type.getString(token_info.obj_ptr)+"!");
}
print("======== Script END ======");
}
script.panic(script.len > count, "scriptObjAddTokens: script.len > count: "+script.len+"!"+count);
},
/* ==================== countWordTokens ================================== */
/* Counts the number of adjoining non-separator.
*
* Returns -ve if the first token is the expansion
* operator (in which case the count doesn't include
* that token).
*/
countWordTokens: function(idx) {
var script = this;
var expand = 1;
var count = 0;
/* Is the first word {*} or {expand}? */
var token_list_info = script.token_list[idx];
if (token_list_info.token == script.TOKEN_STR && !script.TOKEN_IS_SEP(script.token_list[idx + 1].token)) {
if ((token_list_info.len == 1 && script.text.charAt(token_list_info.start) == '*') || (token_list_info.len == 6 && script.text.substring(token_list_info.start, token_list_info.start + 6) == "expand")) {
/* Create an expand token */
expand = -1;
idx++;
token_list_info = script.token_list[idx];
}
}
/* Now count non-separator words */
while (!script.TOKEN_IS_SEP(token_list_info.token)) {
idx++;
token_list_info = script.token_list[idx];
count++;
}
return count * expand;
},
/* ==================== dumpToken ================================== */
dumpToken: function(idx, token_info) {
print("dumpToken["+idx+"]"+script.getTokenString(token_info.token)+"!");
var script = this;
print("["+idx+"]@"+script.getTokenString(token_info.token)+"!"+script.interp.string_obj_type.getString(token_info.obj_ptr)+"!");
},
});
RaplScript.prototype.constructor = RaplScript;
R.RaplScript = RaplScript;
}, "0.0.1", {});