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; }
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; }