Exemple #1
0
LocalVar* push_local_var(const char* name, const QoreProgramLocation& loc, const QoreTypeInfo* typeInfo, bool is_arg, int n_refs, bool top_level) {
   QoreProgram* pgm = getProgram();

   LocalVar* lv = pgm->createLocalVar(name, typeInfo);

   QoreString ls;
   loc.toString(ls);
   //printd(5, "push_local_var() lv: %p name: %s type: %s %s\n", lv, name, typeInfo->getName(), ls.getBuffer());

   bool found_block = false;
   // check stack for duplicate entries
   bool avs = parse_check_parse_option(PO_ASSUME_LOCAL);
   if (is_arg) {
      lv->parseAssigned();
      if (pgm->checkWarning(QP_WARN_DUPLICATE_LOCAL_VARS | QP_WARN_DUPLICATE_BLOCK_VARS) || avs) {
         VNode* vnode = getVStack();
         while (vnode) {
            if (!found_block && vnode->isBlockStart())
               found_block = true;
            if (!strcmp(vnode->getName(), name)) {
	       if (!found_block) {
		  QoreStringNode* desc = new QoreStringNodeMaker("local variable '%s' was already declared in the same block", name);
		  if (avs) {
		     vnode->appendLocation(*desc);
		     parseException(loc, "PARSE-ERRPR", desc);
		  }
		  else {
		     vnode->appendLocation(*desc);
                     qore_program_private::makeParseWarning(getProgram(), loc, QP_WARN_DUPLICATE_BLOCK_VARS, "DUPLICATE-BLOCK-VARIABLE", desc);
		  }
	       }
	       else if (top_level || !vnode->isTopLevel()) {
		  QoreStringNode* desc = new QoreStringNodeMaker("local variable '%s' was already declared in this lexical scope", name);
		  vnode->appendLocation(*desc);
		  qore_program_private::makeParseWarning(getProgram(), loc, QP_WARN_DUPLICATE_LOCAL_VARS, "DUPLICATE-LOCAL-VARIABLE", desc);
	       }
	       break;
	    }
            vnode = vnode->nextSearch();
         }
      }
   }
   
   //printd(5, "push_local_var(): pushing var %s\n", name);
   new VNode(lv, &loc, n_refs, top_level);
   return lv;
}
int SwitchStatement::parseInitImpl(LocalVar *oflag, int pflag) {
   int lvids = 0;

   // turn off top-level flag for statement vars
   pflag &= (~PF_TOP_LEVEL);

   const QoreTypeInfo *argTypeInfo = 0;

   if (sexp)
      sexp = sexp->parseInit(oflag, pflag, lvids, argTypeInfo);

   CaseNode *w = head;
   ExceptionSink xsink;
   QoreProgram *pgm = getProgram();
   while (w) {
      if (w->val) {
         argTypeInfo = 0;
         w->val = w->val->parseInit(oflag, pflag | PF_CONST_EXPRESSION, lvids, argTypeInfo);
	 if (lvids) {
	    parse_error("illegal local variable declaration in assignment expression for case block");
	    while (lvids--)
	       pop_local_var();

	    w = w->next;
	    continue;
	 }

	 // evaluate case expression if necessary and no parse expressions have been raised
	 if (w->val && !w->val->is_value()) {
	    if (pgm->parseExceptionRaised()) {
	       w = w->next;
	       continue;
	    }

	    ReferenceHolder<AbstractQoreNode> v(w->val->eval(&xsink), &xsink);
	    if (!xsink) {
	       w->val->deref(&xsink);
	       w->val = v.release();
	       if (!w->val)
		  w->val = nothing();
	    }
	    else
	       qore_program_private::addParseException(pgm, xsink);
	 }
	 //printd(5, "SwitchStatement::parseInit() this=%p case exp: %p %s\n", this, w->val, get_type_name(w->val));

	 // check for duplicate values
	 CaseNode *cw = head;
	 while (cw != w) {
            // Check only the simple case blocks (case 1: ...),
            // not those with relational operators. Could be changed later to provide more checking.
	    // note that no exception can be raised here as the case node values are parse values
            if (w->isCaseNode() && cw->isCaseNode() && !compareHard(w->val, cw->val, &xsink))
	       parse_error("duplicate case values in switch");
	    assert(!xsink);
	    cw = cw->next;
	 }
      }

      if (w->code)
	 w->code->parseInitImpl(oflag, pflag);
      w = w->next;
   }

   // save local variables
   if (lvids)
      lvars = new LVList(lvids);

   return 0;
}
Exemple #3
0
int ConstantEntry::parseInit(ClassNs ptr) {
   //printd(5, "ConstantEntry::parseInit() this: %p '%s' pub: %d init: %d in_init: %d node: %p '%s' class context: %p '%s' ns: %p ('%s') pub: %d\n", this, name.c_str(), pub, init, in_init, node, get_type_name(node), ptr.getClass(), ptr.getClass() ? ptr.getClass()->name.c_str() : "<none>", ptr.getNs(), ptr.getNs() ? ptr.getNs()->name.c_str() : "<none>", ptr.getNs() ? ptr.getNs()->pub : 0);

   if (init)
      return 0;

   if (in_init) {
      parse_error("recursive constant reference found to constant '%s'", name.c_str());
      return 0;
   }

   ConstantEntryInitHelper ceih(*this);

   if (!node)
      return 0;

   int lvids = 0;

   {
      // set parse location in case of errors
      ParseLocationHelper plh(loc);

      // push parse class context
      qore_class_private* p = ptr.getClass();
      QoreParseClassHelper qpch(p ? p->cls : 0);

      // ensure that there is no accessible local variable state
      VariableBlockHelper vbh;

      // set parse options and warning mask for this statement
      ParseWarnHelper pwh(pwo);

      //printd(5, "ConstantEntry::parseInit() this: %p '%s' about to init node: %p '%s' class: %p '%s'\n", this, name.c_str(), node, get_type_name(node), p, p ? p->name.c_str() : "n/a");
      if (typeInfo)
         typeInfo = 0;

      node = node->parseInit((LocalVar*)0, PF_CONST_EXPRESSION, lvids, typeInfo);
   }

   //printd(5, "ConstantEntry::parseInit() this: %p %s initialized to node: %p (%s) value: %d\n", this, name.c_str(), node, get_type_name(node), node->is_value());

   if (node->is_value())
      return 0;

   // do not evaluate expression if any parse exceptions have been thrown
   QoreProgram* pgm = getProgram();
   if (pgm->parseExceptionRaised()) {
      discard(node, 0);
      node = 0;
      typeInfo = nothingTypeInfo;
      return -1;
   }

   // evaluate expression
   ExceptionSink xsink;
   {
      ReferenceHolder<AbstractQoreNode> v(node->eval(&xsink), &xsink);

      //printd(5, "ConstantEntry::parseInit() this: %p %s evaluated to node: %p (%s)\n", this, name.c_str(), *v, get_type_name(*v));

      if (!xsink) {
	 node->deref(&xsink);
	 node = v.release();
	 if (!node) {
	    node = nothing();
	    typeInfo = nothingTypeInfo;
	 }
	 else {
	    typeInfo = getTypeInfoForValue(node);
	    check_constant_cycle(pgm, node); // address circular refs: pgm->const->pgm
	 }
      }
      else {
	 node->deref(&xsink);
	 node = 0;
	 typeInfo = nothingTypeInfo;
      }
   }

   if (xsink.isEvent())
      qore_program_private::addParseException(pgm, xsink, &loc);

   // scan for call references
   if (scanValue(node)) {
      saved_node = node;
      node = new RuntimeConstantRefNode(refSelf());
   }

   return 0;
}