RAPL

Artifact [6e8aa37507]
Login

Artifact [6e8aa37507]

Artifact 6e8aa37507f0bcad6a1e49c1605155598bc677cf:


/*====================================================
 * rapl_eval_statement.js "A Tcl like language implementation in Javascript named WebRAPL 
 * (Web Rapid Application Programming Language)"
 *
 * evaluate a statement for RAPL also eval execution traces, if necessary
 *
 * Released under the same terms as Tcl itself.
 * (BSD license found at <http://www.tcl.tk/software/tcltk/license.html>)
 *
 * Based on Picol by Salvatore Sanfilippo (<http://antirez.com/page/picol>)
 * (c) Stéphane Arnold 2007
 * Richard Suchenwirth 2007: cleanup, additions
 * Arnulf Wiedemann    2011: a lot of additions for Tcl 8.6 syntax, itcl support
 */

RP.add("rapl-eval-statement", function(R, name) {

/* =============================== EvalStatement ================================== */

function EvalStatement(interp) {
  R.log('constructor called', 'life', 'EvalStatement', true);
  
  // kweight
  var evalstmt = this;
  evalstmt.interp           = interp;
  evalstmt.call_level       = 0;
  evalstmt.eval_level       = 0;
  evalstmt.expr_eval_level  = 0;
  evalstmt.level_infos      = new Array();
  evalstmt.enterstep_traces = new Array();
  evalstmt.leavestep_traces = new Array();
  evalstmt.inLoop           = false;
  evalstmt.level            = 0;
  evalstmt.callframes       = new Array();
  evalstmt.callframes.push(new R.Callframe(evalstmt.interp, evalstmt.CALL_TYPE_PROC));
  evalstmt.curr_callframe   = evalstmt.callframes[evalstmt.level];
  evalstmt.curr_callframe.setNamespace(evalstmt.interp.root_namespace);
  evalstmt.no_trace         = false;
  evalstmt.call_debug       = 0;
  evalstmt.eval_stmt_debug  = 0;
  evalstmt.eval_expr_debug  = 0;
  evalstmt.code             = evalstmt.OK;
  evalstmt.file_name        = null;
  evalstmt.in_quoted_string = false;
  evalstmt.in_brace = false;
  evalstmt.cmd_name = "";
  evalstmt.last_token = 0;

  R.Base.eval_statment_cnt++;
  evalstmt.cnt = R.Base.eval_statement_cnt;
  evalstmt.my_name = "RaplEvalStatement";

  R.log('constructor end', '2.life', 'EvalStatement', true);

}

R.extend(EvalStatement, R.Token, {
  /* ==================== isBracedParam ===================================== */
  isBracedParam: function (val) {
     return (val instanceof TclWord);
  },

  /* ==================== incrLevel ===================================== */
  incrLevel: function(type) {
    var class_object = this.getCallframeClassObject();
    this.level++;
    this.callframes.push(new TclCallframe(this.interp, type));
    this.curr_callframe = this.callframes[this.level];
    this.curr_callframe.setNamespace(this.interp.current_namespace);
    this.curr_callframe.setClassObject(class_object);
    return this.level;
  },

  /* ==================== decrLevel ===================================== */
  decrLevel: function() {
    this.callframes.pop();
    this.level--;
    if (this.level<0) {
      throw "Exit application";
    }
    this.curr_callframe = this.callframes[this.level];
    this.result = null;
  },

  /* ==================== setCallframeClassObject ===================================== */
  setCallframeClassObject: function (class_object) {
    this.curr_callframe.setClassObject(class_object);
  },

  /* ==================== getCallframeClassObject ===================================== */
  getCallframeClassObject: function () {
    return this.curr_callframe.getClassObject();
  },

  /* ==================== evalFileContents ================================ */
  evalFileContents: function (file_name, code) {
    this.interp.curr_file_name = file_name;
    var stmts_obj;
    if (typeof code == "string") {
      stmts_obj = this.statement_parser.parse2Statements(file_name, 1, code);
      return this.eval(stmts_obj);
    } else {
      throw "evalFileContents!"+file_name+"!"+typeof code+"! no type string of code";
    }
  },

  /* ==================== eval ===================================== */
  eval: function (code) {
    try {
//print("EVAL1!"+(code instanceof Array)+"!"+(code instanceof TclStatement)+"!"+code+"!");
//print("EVAL1!"+code.hasStatementsValue()+"!");
//print("CODE!"+typeof code+"!");
      if ((typeof code != "string") && code.hasStatementsValue()) {
//print(">>> eval TCL!"+code+"!");
        var save_statments = this.curr_callframe.curr_statements;
        var save_statment_idx = this.curr_callframe.curr_statement_idx;
	this.curr_callframe.curr_statements = code;
	this.curr_callframe.curr_statement_idx = 0;
        result = this.evalTclStatements();
        this.curr_callframe.curr_statements = save_statments;
        this.curr_callframe.curr_statement_idx = save_statment_idx;
      } else {
//print(">> eval2!"+code+"!"+(code instanceof TclObject)+"!"+typeof code+"!");
        var stmts_obj = null;
        if (typeof code == "string") {
          stmts_obj = this.statement_parser.parse2Statements(this.interp.curr_file_name, this.interp.curr_line_no, code);
        } else {
	  if (!(code instanceof TclObject)) {
            throw "eval code is no string and no TclObject"
	  }
	  if (code.isNoExprOrStatement) {
            stmts_obj = code.toStatements(this.interp.curr_file_name, this.interp.curr_line_no);
	  } else {
            if (!code.hasStatementsValue()) {
              throw "eval code is no string and has no StatementsValue"
            } else {
              stmts_obj = code.getStatementsValue();
            }
          }
	}
//print("EVAL STMTS!"+stmts_obj+"!");
	if (stmts_obj != null) {
          var save_statments = this.curr_callframe.curr_statements;
          var save_statment_idx = this.curr_callframe.curr_statement_idx;
	  this.curr_callframe.curr_statements = stmts_obj;
	  this.curr_callframe.curr_statement_idx = 0;
          result = this.evalTclStatements();
          this.curr_callframe.curr_statements = save_statments;
          this.curr_callframe.curr_statement_idx = save_statment_idx;
	}
      }
//print("EV END!"+code.toString().substring(0,50)+"!"+result+"!");
      return result;
    } catch (e) {
      if (this.code == Tcl.ERROR) {
//        return this.interp.objectify(Tcl.GetErrorCode(this.interp));
      }
for (var i = this.level-1; i >= 0; i--) {
//print("LEVEL_INFO!"+i+"!"+this.level_infos[i]+"!");
}
//print("CODE!"+code.toString()+"!");
      var cmd = code.toString();
print("CCC!"+typeof cmd.substring+"!");
      if (typeof cmd.substring != "undefined") {
        cmd = cmd.substring(0,128);
      }
print("CCC2!"+cmd+"!");
try {
      if(!confirm(e+"/" + e.description + "\nwhile evaluating "+cmd+"...")) {
        throw(e);
      }
} catch(e2) {
print("CCCa!"+e2+"!");
}
print("CCC3!"+cmd+"!");
    }
  },

  /* ==================== evalTclStatement ===================================== */
  evalTclStatement: function(stmt) {
//print("evalTclStatement!"+stmt.toString().substring(0,40)+"!");
//print("DBG!"+stmt.toDebugString()+"!");
    this.in_quoted_string = false;
    var args = new Array();
    var had_expand = false;
    var had_no_word_sep = false;
    var had_cmd = false;
//print("LL!"+typeof stmt+"!"+stmt+"!"+(stmt instanceof TclObject)+"!");
    var statement_file_name = null;
    var statement_line_no = -1;
    var statement_last_line_no = -1;
    this.cmd_name = "";
//print("STMT!"+(stmt instanceof TclStatement)+"!"+stmt.len);
//print("STMT!"+stmt.toDebugString()+"!");
    var save_last_token = this.last_token;
    this.last_token = Tcl.TOKEN_EOF;
    for (var j = 0; j < stmt.len; j++) {
      var word_obj = stmt.getWord(j);
      var word = word_obj.getWordValue();
      var token = word.getToken();
      if (token == Tcl.TOKEN_QUOTED_STR) {
        this.in_quoted_string = true;
      }
      try {
//print("ETS TOK!"+Tcl.getParserTokenString(token)+"!");
        var val = word.getEvalValue();
//print("VAL!"+val+"!");
//print("evalTclSTMT!"+j+"!"+Tcl.getParserTokenString(token)+"!"+val.toString().substring(0,100)+"!");
        var file_name = word.getFileName();
        var last_line_no = word.getLastLineNo();
        var line_no = word.getLineNo();
//print("WORD!"+j+"!"+file_name+"!"+last_line_no+"!"+line_no+"!"+word+"!");
	if (j == 0) {
          this.interp.curr_file_name = file_name;
          this.interp.curr_line_no = line_no;
          this.interp.last_line_no = last_line_no;
          statement_file_name = file_name;
          statement_line_no = line_no;
          statement_last_line_no = last_line_no;
	}
        var val2 = null;
//print("ETS!"+j+"!"+stmt.len+"!"+Tcl.getParserTokenString(token)+"!"+word.toDebugString()+"!");
//print("EVTOK!"+Tcl.getParserTokenString(token)+"!");
        var my_last_token = this.last_token;
        switch(token) {
        case Tcl.TOKEN_EXPR:
//print("evalTclSTMT Tcl.TOKEN_EXPR");
          var result = this.evalExprTree(val);
          break;
        case Tcl.TOKEN_NO_WORD_SEP:
//print("evalTclSTMT Tcl.TOKEN_NO_WORD_SEP");
          had_no_word_sep = true;
          continue;
          break;
        case Tcl.TOKEN_CMD:
          /* evaluation has already been done by getEvalValue !! */
          var result = val;
//print(">>>CMD!"+val+"!");
          args.push(this.interp.statement_parser.objectify(result));
          break;
        case Tcl.TOKEN_BRACE:
//print(">> TOKEN_BRACE!"+val+"!");
          var word_parts = word.getWordParts();
          var my_part = word_parts[0];
          var sub_stmts = my_part.getStatements();
//print("BRACE!"+had_cmd+"!"+sub_stmts+"!"+(val instanceof TclObject)+"!"+my_part+"!"+word_parts.length+"!");
          this.in_brace = true;
          if (had_cmd) {
            if (sub_stmts != null) {
              args.push(new TclObject(this, sub_stmts, "STMTS"));
            } else {
              args.push(word_obj);
            }
            had_cmd = false;
          }else {
//print("TB!"+typeof val+"!"+val+"!");
            args.push(word_obj);
          }
          break;
        case Tcl.TOKEN_STR_CMD:
          had_cmd = true;
	  this.cmd_name = val;
//print(">>>STR_CMD!"+val+"!");
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_STR_PARAM:
//print(">>>STR_PARAM!"+val+"!");
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_EXPAND:
          had_expand = true;
//print("Tcl.TOKEN_EXPAND:!"+val+"!"+(val instanceof Array)+"!"+val.length+"!");
          for (var k = 0; k < val.length; k++) {
            var val2 = val[k];
            args.push(this.interp.statement_parser.objectify(val2));
          }
          break;
        case Tcl.TOKEN_VAR:
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_VAR_ARRAY:
//print("TOKEN_VAR_ARRAY:!"+val+"!");
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_VAR_ARRAY_NAME:
//print("TOKEN_VAR_ARRAY_NAME:!"+val+"!");
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_ARRAY_NAME:
//print("TOKEN_ARRAY_NAME:!"+val+"!");
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_BRACED_VAR:
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_PAREN:
//print("STMT TOKEN_PAREN:!"+val+"!");
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_QUOTED_STR:
          args.push(this.interp.statement_parser.objectify(val));
          break;
        case Tcl.TOKEN_WORD_SEP:
        case Tcl.TOKEN_COMMENT:
        case Tcl.TOKEN_EOL:
        case Tcl.TOKEN_EOF:
//print("special token!"+Tcl.getParserTokenString(token)+"!");
          /* these are only for reconstructing the source code again */
          continue;
        default:
          throw "unexpected token in evalTclStatement!"+Tcl.getParserTokenString(token)+"!";
        }
        had_no_word_sep = false;
      } catch(e) {
print("INNER ERROR");
        throw "ERROR in INNER evalTclStatement:!"+e+"!"+word.toString()+"!";
      }
      this.last_token = token;
    }
    this.last_token = save_last_token;
if (this.eval_stmt_debug) {
print("+++ eval_stmt EOL call!"+args.toString().substring(0,100)+"!");
}
//print("STMT1!"+args.toString().substring(0,60)+"!");
    if (args.length == 0) {
      /* seems to be an emty statement like a comment or an empty line, so nothing to do */
      this.code = Tcl.OK;
      return interp.statement_parser.objectify("");
    }
    try {
//print("SETFL!"+statement_file_name+"!"+statement_last_line_no+"!"+statement_line_no+"!"+this.interp+"!"+this.interp.curr_file_name+"!");
      this.interp.curr_file_name = statement_file_name;
      this.interp.curr_line_no = statement_line_no;
      this.interp.curr_statement = args;
//print("ARGS!"+args+"!");
      result = this.call(args);
    } catch(e) {
      throw "ERROR in CALL evalTclStatements:!"+e+"!"+args+"!";
    }
//print("evalTclStatement result!"+result.toString().substring(0,60)+"!"+stmt+"!");
    return result;
  },

  /* ==================== evalTclStatements ===================================== */
  evalTclStatements: function() {
    try {
      var result = "";
      var statements_obj = this.curr_callframe.curr_statements;
      var statements = statements_obj.getStatementsValue();
      var i = this.curr_callframe.curr_statement_idx
      for (; i < statements.length; i++) {
        this.in_brace = false;
        var stmt_obj = statements[i];
//print("EVTS!"+this.curr_callframe.curr_statement_idx+"!"+statements.length+"!");
//print("EVTS2!"+stmt_obj.getStatementValue().toDebugString()+"!");
//print("EVTS3!"+stmt_obj.getStatementValue().toString()+"!");
//print("EVTS4!"+stmt_obj.getStatementValue().toFullString()+"!");
	this.curr_callframe.curr_statement_idx = i;
	this.code = Tcl.OK;
        result = this.evalTclStatement(stmt_obj.getStatementValue());
//print("EVTS5");
        if (this.code != Tcl.OK) {
	  if (this.code == Tcl.RETURN) {
            return result;
	  }
print(" had Tcl ERROR evalTclStatements call after evalTclStatement!"+this.code+"!"+result+"!");
          result = this.interp.statement_parser.objectify(result);
          return result;
        }
      }
    } catch(e) {
      throw "ERROR in OUTER evalTclStatements:!"+e+"!"+this.interp.current_statement+"!";
    }
    return result;
  },

  /* ==================== call ===================================== */
  call: function(args) {
//print("CALL1");
//this.call_logs.push(args.toString());
if (this.call_debug) {
//print("IPCALL!"+args.toString()+"!");
}
//print("interp.call arg0!"+args[0]+"!length!"+args.length+"!arg1!"+args[1]+"!lv!"+this.level+"!call_lv!"+this.call_level+"!");
    this.call_level++;
//print("CALL2a!"+args[0].toString()+"!");
    if(_step && !confirm("this.call "+args)) {
      throw "user abort";
    }
//print("IPNS1!"+this.interp.current_namespace.full_name+"!");
    var my_cmd = args[0].toString();
    var func = this.interp.getCommand(my_cmd);
//print("CA!"+args[0]+"!"+func+"!");
if (this.call_debug) {
print("interp call func!"+func+"!type!"+func.type+"!name!"+func.name+"!NS!"+this.interp.command_namespace.name+"!");
}
//print("FUNC!"+(func instanceof Tcl.EnsembleCommand)+"!");
    var pushed = 0;
    if ((this.interp.current_namespace != this.interp.command_namespace) && (this.interp.command_namespace.name != "::")) {
      this.interp.pushNamespace(this.interp.command_namespace.name, this.interp.command_namespace);
      pushed = 1;
    }
//print("IPNS!"+this.interp.current_namespace.full_name+"!");
    var my_obj = new TclObject(this.interp, "", "TEXT");
    var function_args = my_obj.getString(args);
    if (!this.no_trace && (this.enterstep_traces.length > 0)) {
      for (var i = 0; i < this.enterstep_traces.length; i++) {
        var trace_obj = this.enterstep_traces[i];
	var ops = trace_obj.getOps();
	for (var j = 0; j < ops.length; j++) {
          if (ops[j] == Tcl.TRACE_OP_ENTERSTEP) {
	    var code = trace_obj.getCommand()+" {"+function_args+"} enter";
            try {
              this.no_trace = true;		    
              this.eval(code);
              this.no_trace = false;		    
            } catch(e) {
              throw "error in executing enterstep trace: "+code+"!";
            }
          }
        }
      }
    }
if (this.call_debug) {
print("CALL!"+args+"!");
}
    var r = func.call(this.interp, args);
if (this.call_debug) {
print("CALL after!"+r+"!");
}
    if (pushed) {
      this.interp.popNamespace();
    }
    if (!this.no_trace && (this.leavestep_traces.length > 0)) {
      for (var i = 0; i < this.leavestep_traces.length; i++) {
        var trace_obj = this.leavestep_traces[i];
	var ops = trace_obj.getOps();
	for (var j = 0; j < ops.length; j++) {
          if (ops[j] == Tcl.TRACE_OP_LEAVESTEP) {
	    var my_obj = new TclObject(this.interp, "", "TEXT");
	    var result = r;
	    if (result == null) {
              result = "";
	    }
	    var code = trace_obj.getCommand()+" {"+function_args+"} "+this.code+" {"+result+"} leavestep";
            try {
              this.no_trace = true;		    
              this.eval(code);
              this.no_trace = false;		    
            } catch(e) {
              throw "error in executing leavestep trace: "+code+"!";
            }
          }
        }
      }
    }
    this.call_level--;
    switch (this.code) {
    case Tcl.OK:
    case Tcl.ERROR:
    case Tcl.RETURN:
      return r;
    case Tcl.BREAK:
      if (!this.inLoop) {
        throw "Invoked break outside of a loop";
      }
      break;
    case Tcl.CONTINUE:
      if (!this.inLoop) {
        throw "Invoked continue outside of a loop";
      }
      break;
    default:
      throw "Unknown return code " + this.code;
    }
    return r;
  },

  /* ==================== evalExprSubTree ===================================== */
  evalExprSubTree: function(node, parent, lv) {
//this.eval_expr_debug = 1;
if (this.eval_expr_debug) {
print("evalExprSubTree!"+lv+"!");
node.showTree(node, "");
}
    var type_left = -1;
    var type_right = -1;
    var type_node = node.getNodeType();
    var name_left = "";
    var name_right = "";
    var val_left = "{}";
    var val_right = "{}";
    var child_left = node.getChildLeft();
    var child_right = node.getChildRight();
    if ((child_left == null) && (child_right == null)) {
if (this.eval_expr_debug) {
print("evalExprSubTree bottom!N!"+node.name+"!"+lv+"!");
}
      return this.interp.statement_parser.objectify(node.getNodeValue());
    }
    if (child_left != null) {
      type_left = child_left.getNodeType();
      name_left = child_left.name;
      if (type_left >= Tcl.TOKEN_MINUS) {
        left_val = this.statement_parser.tree2Expr(child_left, node, "", lv);
      } else {
         val_left = child_left.getNodeValue();
      }
    }
    if (child_right != null) {
      type_right = child_right.getNodeType();
      name_right = child_right.name;
      if (type_right >= Tcl.TOKEN_MINUS) {
        val_right = this.statement_parser.tree2Expr(child_right, node, "", lv);
      } else {
        val_right = child_right.getNodeValue();
      }
    }
if (this.eval_expr_debug) {
print("evalExprSubTree!N!"+node.name+"!L!"+name_left+"!T!"+type_left+"!V!"+val_left+"!R!"+name_right+"!T!"+type_right+"!V!"+val_right+"!"+lv+"!");
}
    lv++;
    var val;
    if ((type_left < Tcl.TOKEN_PAREN) && (type_right < Tcl.TOKEN_PAREN) && (type_node != Tcl.TOKEN_NOT)) {
      left_val = child_left.getNodeValue();
      right_val = child_right.getNodeValue();
      var  code = node.name+" "+left_val+" "+right_val;
      if (Tcl.isStringOperatorType(node.getNodeType())) {
        code = node.name+" {"+left_val+"} {"+right_val+"}";
      }
//print("ESU!"+code+"!");
      val = this.eval(code);
      lv--;
      return this.interp.statement_parser.objectify(val);
    }
    var left_val;
    var right_val;
    if ((child_left == null) && (child_right == null)) {
      lv--;
      return this.interp.statement_parser.objectify(node.getNodeValue());
    }
    if ((type_left == Tcl.TOKEN_STR) || (type_left == Tcl.TOKEN_VAR)) {
      left_val = child_left.getNodeValue();
    } else {
      if (type_left == Tcl.TOKEN_PAREN) {
        left_val = this.statement_parser.tree2Expr(child_left.getChildLeft(), node, "", lv);
      } else {
        left_val = this.statement_parser.tree2Expr(child_left, node, "", lv);
      }
    }

    if (node.getNodeType() == Tcl.TOKEN_NOT) {
      if (left_val == 0) {
        val = this.interp.statement_parser.objectify("1");
      } else {
        val = this.interp.statement_parser.objectify("0");
      }
if (this.eval_expr_debug) {
print("RET NOT!"+val+"!"+node.name+"!"+left_val+"!");
}
      return val;
      lv--;
    }
    if (child_right == null) {
      lv--;
      return this.interp.statement_parser.objectify(left_val);
    }

    if (type_right == Tcl.TOKEN_STR) {
      right_val = child_right.getNodeValue();
    } else {
      if (type_right == Tcl.TOKEN_PAREN) {
        right_val = this.statement_parser.tree2Expr(child_right.getChildLeft(), node, "", lv);
      } else {
        right_val = this.statement_parser.tree2Expr(child_right, node, "", lv);
      }
    }

    var  code = node.name+" "+left_val+" "+right_val;
    if (Tcl.isStringOperatorType(node.getNodeType())) {
      code = node.name+" {"+left_val+"} {"+right_val+"}";
    }
    val = this.eval(code);
if (this.eval_expr_debug) {
print("RET!"+val+"!"+node.name);
}
    lv--;
    return this.interp.statement_parser.objectify(val);
  },

  /* ==================== evalExprTree ===================================== */
  evalExprTree: function(word) {
    var node = word.getValue();
//print("evalExprTree!"+typeof node+"!");
//node.showTree(node, "");
    var result = this.evalExprSubTree(node, null, 0);
    result = this.interp.statement_parser.objectify(result);
//print("evalExprTree!"+result+"!");
    return result;
  },

});

EvalStatement.prototype.constructor = EvalStatement;

R.EvalStatement = EvalStatement;

}, "0.0.1", {});