Esempio n. 1
0
Exec_stat MCComref::exec(MCExecPoint &ep)
{
	if (MCscreen->abortkey())
	{
		MCeerror->add(EE_HANDLER_ABORT, line, pos);
		return ES_ERROR;
	}

	if (!resolved)
	{
		// MW-2008-01-28: [[ Inherited parentScripts ]]
		// If we are in parentScript context, then the object we search for
		// private handlers in is the parentScript's object, rather than the
		// ep's.
		MCParentScriptUse *t_parentscript;
		t_parentscript = ep . getparentscript();

		MCObject *t_object;
		if (t_parentscript == NULL)
			t_object = ep . getobj();
		else
			t_object = t_parentscript -> GetParent() -> GetObject();

		// MW-2008-10-28: [[ ParentScripts ]] Private handlers are resolved
		//   relative to the object containing the handler we are executing.
		MCHandler *t_resolved_handler;
		t_resolved_handler = t_object -> findhandler(HT_MESSAGE, name);
		if (t_resolved_handler != NULL && t_resolved_handler -> isprivate())
			handler = t_resolved_handler;

		resolved = true;
		}

	Exec_stat stat;
	MCParameter *tptr = params;
	while (tptr != NULL)
	{
		MCVariable* t_var;
		t_var = tptr -> evalvar(ep);

		if (t_var == NULL)
		{
			tptr -> clear_argument();
			while ((stat = tptr->eval(ep)) != ES_NORMAL && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
				MCB_error(ep, line, pos, EE_STATEMENT_BADPARAM);
			if (stat != ES_NORMAL)
			{
				MCeerror->add(EE_STATEMENT_BADPARAM, line, pos);
				return ES_ERROR;
			}
			tptr->set_argument(ep);
		}
		else
			tptr->set_argument_var(t_var);

		tptr = tptr->getnext();

	}
	MCObject *p = ep.getobj();
	MCExecPoint *oldep = MCEPptr;
	MCEPptr = &ep;
	stat = ES_NOT_HANDLED;
	Boolean added = False;
	if (MCnexecutioncontexts < MAX_CONTEXTS)
	{
		ep.setline(line);
		MCexecutioncontexts[MCnexecutioncontexts++] = &ep;
		added = True;
	}

	if (handler != nil)
	{
		// MW-2008-10-28: [[ ParentScripts ]] If we are in the context of a
		//   parent, then use a special method.
		if (ep . getparentscript() == NULL)
			stat = p -> exechandler(handler, params);
		else
			stat = p -> execparenthandler(handler, params, ep . getparentscript());

		switch(stat)
		{
		case ES_ERROR:
		case ES_PASS:
			MCeerror->add(EE_STATEMENT_BADCOMMAND, line, pos, handler -> getname());
			if (MCerrorptr == NULL)
				MCerrorptr = p;
			stat = ES_ERROR;
			break;

		case ES_EXIT_HANDLER:
			stat = ES_NORMAL;
			break;

		default:
			break;
		}
	}
	else
	{
		stat = MCU_dofrontscripts(HT_MESSAGE, name, params);
		Boolean olddynamic = MCdynamicpath;
		MCdynamicpath = MCdynamiccard != NULL;
		if (stat == ES_PASS || stat == ES_NOT_HANDLED)
			switch (stat = p->handle(HT_MESSAGE, name, params, p))
			{
			case ES_ERROR:
			case ES_NOT_FOUND:
			case ES_NOT_HANDLED:
			case ES_PASS:
				MCeerror->add(EE_STATEMENT_BADCOMMAND, line, pos, name);
				stat = ES_ERROR;
				break;
			case ES_EXIT_HANDLER:
				stat = ES_NORMAL;
				break;
			default:
				break;
			}
		MCdynamicpath = olddynamic;
	}
	MCEPptr = oldep;
	if (added)
		MCnexecutioncontexts--;
	return stat;
}
Esempio n. 2
0
Exec_stat MCFunction::evalparams(Functions func, MCParameter *params,
                                 MCExecPoint &ep)
{
	uint4 nparams = 0;
	real8 n, tn, oldn;
	n = oldn = 0.0;
	MCSortnode *mditems = NULL;
	// JS-2013-06-19: [[ StatsFunctions ]] Support for new stats functions based on arithmeticMean
	if (func == F_AVG_DEV || func == F_POP_STD_DEV || func == F_POP_VARIANCE || func == F_SMP_STD_DEV || func == F_SMP_VARIANCE)
	{ //use recursion to get average first
		if (evalparams(F_ARI_MEAN, params, ep) != ES_NORMAL)
			return ES_ERROR;
		oldn = ep.getnvalue();
	}
	// JS-2013-06-19: [[ StatsFunctions ]] Support for geometricMean
	if (func == F_GEO_MEAN)
	{ //use recursion to count items first
		if (evalparams(F_UNDEFINED, params, ep) != ES_NORMAL)
			return ES_ERROR;
		oldn = ep.getnvalue();
	}
	if (func == F_MEDIAN)
	{ //use recursion to count items first
		if (evalparams(F_UNDEFINED, params, ep) != ES_NORMAL)
			return ES_ERROR;
		mditems = new MCSortnode[(uint4)ep.getnvalue()];
	}
	if (params != NULL && params->getnext() == NULL)
	{
		if (params->eval(ep) != ES_NORMAL)
		{
			MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
			return ES_ERROR;
		}
		if (ep.getformat() == VF_ARRAY)
		{
			if (ep.getarray() -> is_array() && ep.getarray()->get_array()->dofunc(ep, func, nparams, n, oldn, mditems) != ES_NORMAL)
			{
				MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
				return ES_ERROR;
			}
		}
		else
		{
			MCString s(ep.getsvalue());
			uint4 length = s.getlength();
			const char *sptr = s.getstring();
			MCU_skip_spaces(sptr, length);
			while (length != 0)
			{
				s.setstring(sptr);
				if (!MCU_strchr(sptr, length, ','))
				{
					s.setlength(length);
					length = 0;
				}
				else
				{
					s.setlength(sptr - s.getstring());
					MCU_skip_char(sptr, length);
					MCU_skip_spaces(sptr, length);
				}
				if (s.getlength() == 0)
					tn = 0.0;
				else
					if (!MCU_stor8(s, tn))
					{
						MCeerror->add
						(EE_FUNCTION_NAN, 0, 0, s);
						return ES_ERROR;
					}
				MCU_dofunc(func, nparams, n, tn, oldn, mditems);
			}
		}
	}
	else
	{
		MCParameter *tparam = params;
		while (tparam != NULL)
		{
			if (tparam->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
			{
				MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
				return ES_ERROR;
			}
			MCU_dofunc(func, nparams, n, ep.getnvalue(), oldn, mditems);
			tparam = tparam->getnext();
		}
	}
	
	if (nparams != 0)
		switch (func)
	{
		// JS-2013-06-19: [[ StatsFunctions ]] Support for arithmeticMean (was average)
		case F_ARI_MEAN:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for averageDeviation
		case F_AVG_DEV:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for harmonicMean
		case F_HAR_MEAN:
			n = nparams/n;
			break;
		case F_MEDIAN:
			{
				uint4 toffset;
				MCU_sort(mditems, nparams, ST_ASCENDING, ST_NUMERIC);
				toffset = (nparams + 1)/2 - 1;
				if ((nparams % 2) != 0) //odd
					n = mditems[toffset].nvalue;
				else //even average 2 closest values
					n = (mditems[toffset].nvalue + mditems[toffset+1].nvalue)/2;
				break;
			}
		// JS-2013-06-19: [[ StatsFunctions ]] Support for populationStandardDeviation
		case F_POP_STD_DEV:
			n = sqrt(n/nparams);
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for populationVariance
		case F_POP_VARIANCE:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for sampleStandardDeviation (was stdDev)
		case F_SMP_STD_DEV:
			n = sqrt(n/(nparams - 1));
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for sampleVariance
		case F_SMP_VARIANCE:
			n /= nparams - 1;
			break;
		case F_UNDEFINED:
			n = nparams;
			break;
		default:
			break;
		}
	ep.setnvalue(n);
	delete mditems;
	return ES_NORMAL;
}
Esempio n. 3
0
Parse_stat MCStatement::getparams(MCScriptPoint &sp, MCParameter **params)
{
	Boolean needparam = False;
	MCParameter *pptr = NULL;
	while (True)
	{
		if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL)
		{
			sp.backup();
			return PS_NORMAL;
		}
		Symbol_type type;
		switch (sp.next(type))
		{
		case PS_NORMAL:
			sp.backup();
			break;
		case PS_ERROR:
			return PS_ERROR;
		case PS_EOL:
		case PS_EOF:
			if (needparam)
			{
				MCperror->add
				(PE_STATEMENT_BADPARAM, sp);
				return PS_ERROR;
			}
			return PS_NORMAL;
		default:
			sp.backup();
			return PS_NORMAL;
		}
		MCParameter *newptr = new MCParameter;
		if (newptr->parse(sp) != PS_NORMAL)
		{
			delete newptr;
			MCperror->add
			(PE_STATEMENT_BADPARAM, sp);
			return PS_ERROR;
		}
		if (pptr == NULL)
			*params = pptr = newptr;
		else
		{
			pptr->setnext(newptr);
			pptr = newptr;
		}
		if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL)
		{
			sp.backup();
			return PS_NORMAL;
		}
		switch (sp.next(type))
		{
		case PS_NORMAL:
			break;
		case PS_EOL:
		case PS_EOF:
			return PS_NORMAL;
		default:
			MCperror->add
			(PE_STATEMENT_NOTSEP, sp);
			return PS_ERROR;
		}
		if (type != ST_SEP)
		{
			MCperror->add
			(PE_STATEMENT_BADSEP, sp);
			return PS_ERROR;
		}
		needparam = True;
	}
	return PS_NORMAL;
}
Esempio n. 4
0
void MCKeywordsExecCommandOrFunction(MCExecContext& ctxt, bool resolved, MCHandler *handler, MCParameter *params, MCNameRef name, uint2 line, uint2 pos, bool global_handler, bool is_function)
{    
	if (MCscreen->abortkey())
	{
		ctxt . LegacyThrow(EE_HANDLER_ABORT);
		return;
	}
    
	if (!resolved)
	{
		// MW-2008-01-28: [[ Inherited parentScripts ]]
		// If we are in parentScript context, then the object we search for
		// private handlers in is the parentScript's object, rather than the
		// ep's.
		MCParentScriptUse *t_parentscript;
		t_parentscript = ctxt . GetParentScript();
        
		MCObject *t_object;
		if (t_parentscript == NULL)
			t_object = ctxt . GetObject();
        else
            t_object = t_parentscript -> GetParent() -> GetObject();
        
        // MW-2008-10-28: [[ ParentScripts ]] Private handlers are resolved
        //   relative to the object containing the handler we are executing.
        MCHandler *t_resolved_handler;
		t_resolved_handler = t_object -> findhandler(is_function ? HT_FUNCTION : HT_MESSAGE, name);
		if (t_resolved_handler != NULL && t_resolved_handler -> isprivate())
			handler = t_resolved_handler;
        
        resolved = true;
    }
	
    if (is_function)
        MCexitall = False;
    
	// Go through all the parameters to the function, if they are not variables, clear their current value. Each parameter stores an expression
	// which allows its value to be re-evaluated in a given context. Re-evaluate each in the context of ep and set it to the new value.
	// As the ep should contain the context of the caller at this point, the expression should be evaluated in that context.
    Exec_stat stat;
	MCParameter *tptr = params;
	while (tptr != NULL)
	{
        // AL-2014-08-20: [[ ArrayElementRefParams ]] Use containers for potential reference parameters
        MCAutoPointer<MCContainer> t_container = new (nothrow) MCContainer;
        if (tptr -> evalcontainer(ctxt, **t_container))
            tptr -> set_argument_container(t_container.Release());
        else
        {
            tptr -> clear_argument();
            MCExecValue t_value;
            //HERE
            if (!ctxt . TryToEvaluateParameter(tptr, line, pos, is_function ? EE_FUNCTION_BADSOURCE : EE_STATEMENT_BADPARAM, t_value))
                return;
            tptr->give_exec_argument(t_value);
        }
        
        tptr = tptr->getnext();
    }
	MCObject *p = ctxt . GetObject();
	MCExecContext *oldctxt = MCECptr;
	MCECptr = &ctxt;
	stat = ES_NOT_HANDLED;
	Boolean added = False;
	if (MCnexecutioncontexts < MAX_CONTEXTS)
	{
		ctxt . SetLineAndPos(line, pos);
		MCexecutioncontexts[MCnexecutioncontexts++] = &ctxt;
		added = True;
	}
    
    if (handler != nil)
	{
        // MW-2008-10-28: [[ ParentScripts ]] If we are in the context of a
        //   parent, then use a special method.
        if (ctxt . GetParentScript() == nil)
            stat = p -> exechandler(handler, params);
        else
            stat = p -> execparenthandler(handler, params, ctxt . GetParentScript());
        
        switch(stat)
        {
            case ES_ERROR:
            case ES_PASS:
                MCeerror->add(is_function ? EE_FUNCTION_BADFUNCTION : EE_STATEMENT_BADCOMMAND, line, pos, handler -> getname());
                if (!MCerrorptr)
                    MCerrorptr = p;
                stat = ES_ERROR;
                break;
                
            case ES_EXIT_HANDLER:
                stat = ES_NORMAL;
                break;
                
            default:
                break;
        }
	}
	else
	{
		stat = MCU_dofrontscripts(is_function ? HT_FUNCTION : HT_MESSAGE, name, params);
		Boolean olddynamic = MCdynamicpath;
		MCdynamicpath = MCdynamiccard.IsValid();
		if (stat == ES_PASS || stat == ES_NOT_HANDLED)
        {
            if (is_function)
            {
                // PASS STATE FIX
                Exec_stat oldstat = stat;
                stat = p->handle(HT_FUNCTION, name, params, p);
                if (oldstat == ES_PASS && stat == ES_NOT_HANDLED)
                    stat = ES_PASS;
            }
            else
            {
                switch (stat = p->handle(HT_MESSAGE, name, params, p))
                {
                    case ES_ERROR:
                    case ES_NOT_FOUND:
                    case ES_NOT_HANDLED:
                    case ES_PASS:
                        if (!global_handler)
                        {
                            MCeerror->add(EE_STATEMENT_BADCOMMAND, line, pos, name);
                            stat = ES_ERROR;
                        }
                        break;
                    case ES_EXIT_HANDLER:
                        stat = ES_NORMAL;
                        break;
                    default:
                        break;
                }
            }
            
            if (global_handler && (stat == ES_NOT_FOUND || stat == ES_NOT_HANDLED))
            {
                if (!MCRunGlobalHandler(name, params, stat))
                    stat = ES_NOT_HANDLED;
                
                // AL-2014-03-14: Currently no mobile handler's execution is halted when ES_ERROR
                //  is returned. Error info is returned via the result.
#ifdef _MOBILE
                if (stat != ES_NOT_HANDLED)
                    stat = ES_NORMAL;
#endif
            }
        }
		
		MCdynamicpath = olddynamic;
	}
	MCECptr = oldctxt;
	if (added)
		MCnexecutioncontexts--;
    
    if (stat != ES_NORMAL && stat != ES_PASS && stat != ES_EXIT_HANDLER)
        ctxt . SetExecStat(stat);
    else
        ctxt . SetExecStat(ES_NORMAL);

    // AL-2014-09-17: [[ Bug 13465 ]] Clear parameters after executing command/function
    tptr = params;
    while (tptr != NULL)
	{
        tptr -> clear_argument();
        tptr = tptr->getnext();
    }
}