Beispiel #1
0
static int subtract_naive_lhs(Process *p, ErtsSubtractContext *context) {
    const Sint CHECKS_PER_RED = 16;
    Sint checks, budget;

    budget = CHECKS_PER_RED * ERTS_BIF_REDS_LEFT(p);
    checks = 0;

    while (checks < budget && is_list(context->iterator)) {
        const Eterm *cell;
        Eterm value, next;
        int found_at;

        cell = list_val(context->iterator);

        value = CAR(cell);
        next = CDR(cell);

        for (found_at = 0; found_at < context->lhs_remaining; found_at++) {
            if (EQ(value, context->u.lhs_elements[found_at])) {
                /* We shift the array one step down as we have to preserve
                 * order.
                 *
                 * Note that we can't exit early as that would suppress errors
                 * in the right-hand side (this runs prior to determining the
                 * length of RHS). */

                context->lhs_remaining--;
                sys_memmove(&context->u.lhs_elements[found_at],
                            &context->u.lhs_elements[found_at + 1],
                            (context->lhs_remaining - found_at) * sizeof(Eterm));
                break;
            }
        }

        checks += MAX(1, context->lhs_remaining);
        context->iterator = next;
    }

    BUMP_REDS(p, MIN(checks, budget) / CHECKS_PER_RED);

    if (is_list(context->iterator)) {
        return 0;
    } else if (!is_nil(context->iterator)) {
        return -1;
    }

    if (context->lhs_remaining > 0) {
        Eterm *hp;
        int i;

        hp = HAlloc(p, context->lhs_remaining * 2);

        for (i = context->lhs_remaining - 1; i >= 0; i--) {
            Eterm value = context->u.lhs_elements[i];

            context->result = CONS(hp, value, context->result);
            hp += 2;
        }
    }

    ASSERT(context->lhs_remaining > 0 || context->result == NIL);

    return 1;
}
Beispiel #2
0
Obj restExps(Obj seq) {
	// return MKOBJ(LIST, list, CDR(GETLIST(seq)));
	return LISTOBJ(CDR(GETLIST(seq)));
}
Beispiel #3
0
Obj beginActions(Obj expr) {
	return LISTOBJ(CDR(GETLIST(expr)));
}
Beispiel #4
0
SEXP Rprofmem(SEXP args)
{
    return do_Rprofmem(CDR(args));
}
Beispiel #5
0
bool isLastArg(Obj expr) {
	return CDR(GETLIST(expr)) == NULL;
}
Beispiel #6
0
/* .External */
SEXP ocl_call(SEXP args) {
    struct arg_chain *float_args = 0;
    ocl_call_context_t *occ;
    int on, an = 0, ftype = FT_DOUBLE, ftsize, ftres, async;
    SEXP ker = CADR(args), olen, arg, res, octx, dimVec;
    cl_kernel kernel = getKernel(ker);
    cl_context context;
    cl_command_queue commands;
    cl_device_id device_id = getDeviceID(getAttrib(ker, Rf_install("device")));
    cl_mem output;
    size_t wdims[3] = {0, 0, 0};
    int wdim = 1;

    if (clGetKernelInfo(kernel, CL_KERNEL_CONTEXT, sizeof(context), &context, NULL) != CL_SUCCESS || !context)
	Rf_error("cannot obtain kernel context via clGetKernelInfo");
    args = CDDR(args);
    res = Rf_getAttrib(ker, install("precision"));
    if (TYPEOF(res) == STRSXP && LENGTH(res) == 1 && CHAR(STRING_ELT(res, 0))[0] != 'd')
	ftype = FT_SINGLE;
    ftsize = (ftype == FT_DOUBLE) ? sizeof(double) : sizeof(float);
    olen = CAR(args);  /* size */
    args = CDR(args);
    on = Rf_asInteger(olen);
    if (on < 0)
	Rf_error("invalid output length");
    ftres = (Rf_asInteger(CAR(args)) == 1) ? 1 : 0;  /* native.result */
    if (ftype != FT_SINGLE) ftres = 0;
    args = CDR(args);
    async = (Rf_asInteger(CAR(args)) == 1) ? 0 : 1;  /* wait */
    args = CDR(args);
    dimVec = coerceVector(CAR(args), INTSXP);  /* dim */
    wdim = LENGTH(dimVec);
    if (wdim > 3)
	Rf_error("OpenCL standard only supports up to three work item dimensions - use index vectors for higher dimensions");
    if (wdim) {
	int i; /* we don't use memcpy in case int and size_t are different */
	for (i = 0; i < wdim; i++)
	    wdims[i] = INTEGER(dimVec)[i];
    }
    if (wdim < 1 || wdims[0] < 1 || (wdim > 1 && wdims[1] < 1) || (wdim > 2 && wdims[2] < 1))
	Rf_error("invalid dimensions - muse be a numeric vector with positive values");

    args = CDR(args);
    occ = (ocl_call_context_t*) calloc(1, sizeof(ocl_call_context_t));
    if (!occ) Rf_error("unable to allocate ocl_call context");
    octx = PROTECT(R_MakeExternalPtr(occ, R_NilValue, R_NilValue));
    R_RegisterCFinalizerEx(octx, ocl_call_context_fin, TRUE);

    occ->output = output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, ftsize * on, NULL, &last_ocl_error);
    if (!output)
	Rf_error("failed to create output buffer of %d elements via clCreateBuffer (%d)", on, last_ocl_error);
    if (clSetKernelArg(kernel, an++, sizeof(cl_mem), &output) != CL_SUCCESS)
	Rf_error("failed to set first kernel argument as output in clSetKernelArg");
    if (clSetKernelArg(kernel, an++, sizeof(on), &on) != CL_SUCCESS)
	Rf_error("failed to set second kernel argument as output length in clSetKernelArg");
    occ->commands = commands = clCreateCommandQueue(context, device_id, 0, &last_ocl_error);
    if (!commands)
	ocl_err("clCreateCommandQueue");
    if (ftype == FT_SINGLE) /* need conversions, create floats buffer */
	occ->float_args = float_args = arg_alloc(0, 32);
    while ((arg = CAR(args)) != R_NilValue) {
	int n, ndiv = 1;
	void *ptr;
	size_t al;
	
	switch (TYPEOF(arg)) {
	case REALSXP:
	    if (ftype == FT_SINGLE) {
		int i;
		float *f;
		double *d = REAL(arg);
		n = LENGTH(arg);
		f = (float*) malloc(sizeof(float) * n);
		if (!f)
		    Rf_error("unable to allocate temporary single-precision memory for conversion from a double-precision argument vector of length %d", n);
		for (i = 0; i < n; i++) f[i] = d[i];
		ptr = f;
		al = sizeof(float);
		arg_add(float_args, ptr);
	    } else {
		ptr = REAL(arg);
		al = sizeof(double);
	    }
	    break;
	case INTSXP:
	    ptr = INTEGER(arg);
	    al = sizeof(int);
	    break;
	case LGLSXP:
	    ptr = LOGICAL(arg);
	    al = sizeof(int);
	    break;
	case RAWSXP:
	    if (inherits(arg, "clFloat")) {
		ptr = RAW(arg);
		ndiv = al = sizeof(float);
		break;
	    }
	default:
	    Rf_error("only numeric or logical kernel arguments are supported");
	    /* no-ops but needed to make the compiler happy */
	    ptr = 0;
	    al = 0;
	}
	n = LENGTH(arg);
	if (ndiv != 1) n /= ndiv;
	if (n == 1) {/* scalar */
	    if ((last_ocl_error = clSetKernelArg(kernel, an++, al, ptr)) != CL_SUCCESS)
		Rf_error("Failed to set scalar kernel argument %d (size=%d, error code %d)", an, al, last_ocl_error);
	} else {
	    cl_mem input = clCreateBuffer(context,  CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,  al * n, ptr, &last_ocl_error);
	    if (!input)
		Rf_error("Unable to create buffer (%d elements, %d bytes each) for vector argument %d (oclError %d)", n, al, an, last_ocl_error);
	    if (!occ->mem_objects)
		occ->mem_objects = arg_alloc(0, 32);
	    arg_add(occ->mem_objects, input);
#if 0 /* we used this before CL_MEM_USE_HOST_PTR */
	    if ((last_ocl_error = clEnqueueWriteBuffer(commands, input, CL_TRUE, 0, al * n, ptr, 0, NULL, NULL)) != CL_SUCCESS)
		Rf_error("Failed to transfer data (%d elements) for vector argument %d (oclError %d)", n, an, last_ocl_error);
#endif
	    if ((last_ocl_error = clSetKernelArg(kernel, an++, sizeof(cl_mem), &input)) != CL_SUCCESS)
		Rf_error("Failed to set vector kernel argument %d (size=%d, length=%d, error %d)", an, al, n, last_ocl_error);
	    /* clReleaseMemObject(input); */
	}
	args = CDR(args);
    }

    if ((last_ocl_error = clEnqueueNDRangeKernel(commands, kernel, wdim, NULL, wdims, NULL, 0, NULL, async ? &occ->event : NULL)) != CL_SUCCESS)
	ocl_err("Kernel execution");

    if (async) { /* asynchronous call -> get out and return the context */
#if USE_OCL_COMPLETE_CALLBACK
	last_ocl_error = clSetEventCallback(occ->event, CL_COMPLETE, ocl_complete_callback, occ);
#endif
	clFlush(commands); /* the specs don't guarantee execution unless clFlush is called */
	occ->ftres = ftres;
	occ->ftype = ftype;
	occ->on = on;
	Rf_setAttrib(octx, R_ClassSymbol, mkString("clCallContext"));
	UNPROTECT(1);
	return octx;
    }

    clFinish(commands);
    occ->finished = 1;

    /* we can release input memory objects now */
    if (occ->mem_objects) {
      arg_free(occ->mem_objects, (afin_t) clReleaseMemObject);
      occ->mem_objects = 0;
    }
    if (float_args) {
      arg_free(float_args, 0);
      float_args = occ->float_args = 0;
    }

    res = ftres ? Rf_allocVector(RAWSXP, on * sizeof(float)) : Rf_allocVector(REALSXP, on);
    if (ftype == FT_SINGLE) {
	if (ftres) {
	  if ((last_ocl_error = clEnqueueReadBuffer( commands, output, CL_TRUE, 0, sizeof(float) * on, RAW(res), 0, NULL, NULL )) != CL_SUCCESS)
		Rf_error("Unable to transfer result vector (%d float elements, oclError %d)", on, last_ocl_error);
	    PROTECT(res);
	    Rf_setAttrib(res, R_ClassSymbol, mkString("clFloat"));
	    UNPROTECT(1);
	} else {
	    /* float - need a temporary buffer */
	    float *fr = (float*) malloc(sizeof(float) * on);
	    double *r = REAL(res);
	    int i;
	    if (!fr)
		Rf_error("unable to allocate memory for temporary single-precision output buffer");
	    occ->float_out = fr;
	    if ((last_ocl_error = clEnqueueReadBuffer( commands, output, CL_TRUE, 0, sizeof(float) * on, fr, 0, NULL, NULL )) != CL_SUCCESS)
		Rf_error("Unable to transfer result vector (%d float elements, oclError %d)", on, last_ocl_error);
	    for (i = 0; i < on; i++)
		r[i] = fr[i];
	}
    } else if ((last_ocl_error = clEnqueueReadBuffer( commands, output, CL_TRUE, 0, sizeof(double) * on, REAL(res), 0, NULL, NULL )) != CL_SUCCESS)
	Rf_error("Unable to transfer result vector (%d double elements, oclError %d)", on, last_ocl_error);

    ocl_call_context_fin(octx);
    UNPROTECT(1);
    return res;
}
Beispiel #7
0
/* make-one-assert */
	obj_t BGl_makezd2onezd2assertz00zzexpand_assertz00(obj_t BgL_ez00_17,
		obj_t BgL_expz00_18, obj_t BgL_varsz00_19, obj_t BgL_predz00_20)
	{
		AN_OBJECT;
		{	/* Expand/assert.scm 47 */
			{	/* Expand/assert.scm 48 */
				obj_t BgL_predz00_247;

				if (NULLP(BgL_predz00_20))
					{	/* Expand/assert.scm 49 */
						obj_t BgL_list1708z00_315;

						BgL_list1708z00_315 = MAKE_PAIR(BUNSPEC, BNIL);
						BgL_predz00_247 = BgL_list1708z00_315;
					}
				else
					{	/* Expand/assert.scm 48 */
						BgL_predz00_247 = BgL_predz00_20;
					}
				{	/* Expand/assert.scm 48 */
					obj_t BgL_oldzd2predzd2_248;

					BgL_oldzd2predzd2_248 = BGl_dupz00zzexpand_assertz00(BgL_predz00_247);
					{	/* Expand/assert.scm 51 */

						{	/* Expand/assert.scm 52 */
							obj_t BgL_arg1635z00_249;

							obj_t BgL_arg1636z00_250;

							BgL_arg1635z00_249 = CNST_TABLE_REF(((long) 3));
							{	/* Expand/assert.scm 52 */
								obj_t BgL_arg1637z00_251;

								obj_t BgL_arg1639z00_252;

								{	/* Expand/assert.scm 52 */
									obj_t BgL_arg1645z00_257;

									BgL_arg1645z00_257 =
										BGl_expandzd2prognzd2zz__prognz00(BgL_predz00_247);
									BgL_arg1637z00_251 =
										PROCEDURE_ENTRY(BgL_ez00_17) (BgL_ez00_17,
										BgL_arg1645z00_257, BgL_ez00_17, BEOA);
								}
								{	/* Expand/assert.scm 54 */
									obj_t BgL_arg1646z00_258;

									obj_t BgL_arg1647z00_259;

									BgL_arg1646z00_258 = CNST_TABLE_REF(((long) 4));
									{	/* Expand/assert.scm 56 */
										obj_t BgL_arg1650z00_260;

										obj_t BgL_arg1651z00_261;

										{
											obj_t BgL_varsz00_264;

											obj_t BgL_defsz00_265;

											BgL_varsz00_264 = BgL_varsz00_19;
											BgL_defsz00_265 = BNIL;
										BgL_zc3anonymousza31652ze3z83_266:
											if (NULLP(BgL_varsz00_264))
												{	/* Expand/assert.scm 58 */
													BgL_arg1650z00_260 = BgL_defsz00_265;
												}
											else
												{	/* Expand/assert.scm 60 */
													obj_t BgL_arg1654z00_268;

													obj_t BgL_arg1655z00_269;

													BgL_arg1654z00_268 = CDR(BgL_varsz00_264);
													{	/* Expand/assert.scm 61 */
														obj_t BgL_arg1657z00_270;

														{	/* Expand/assert.scm 61 */
															obj_t BgL_arg1659z00_271;

															obj_t BgL_arg1660z00_272;

															BgL_arg1659z00_271 = CNST_TABLE_REF(((long) 5));
															{	/* Expand/assert.scm 61 */
																obj_t BgL_arg1662z00_273;

																obj_t BgL_arg1663z00_274;

																{	/* Expand/assert.scm 61 */
																	obj_t BgL_arg1667z00_278;

																	obj_t BgL_arg1668z00_279;

																	BgL_arg1667z00_278 =
																		CNST_TABLE_REF(((long) 6));
																	{	/* Expand/assert.scm 61 */
																		obj_t BgL_arg1669z00_280;

																		BgL_arg1669z00_280 = CAR(BgL_varsz00_264);
																		{	/* Expand/assert.scm 61 */
																			obj_t BgL_list1671z00_282;

																			BgL_list1671z00_282 =
																				MAKE_PAIR(BNIL, BNIL);
																			BgL_arg1668z00_279 =
																				BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																				(BgL_arg1669z00_280,
																				BgL_list1671z00_282);
																	}}
																	BgL_arg1662z00_273 =
																		MAKE_PAIR(BgL_arg1667z00_278,
																		BgL_arg1668z00_279);
																}
																BgL_arg1663z00_274 = CAR(BgL_varsz00_264);
																{	/* Expand/assert.scm 61 */
																	obj_t BgL_list1665z00_276;

																	{	/* Expand/assert.scm 61 */
																		obj_t BgL_arg1666z00_277;

																		BgL_arg1666z00_277 = MAKE_PAIR(BNIL, BNIL);
																		BgL_list1665z00_276 =
																			MAKE_PAIR(BgL_arg1663z00_274,
																			BgL_arg1666z00_277);
																	}
																	BgL_arg1660z00_272 =
																		BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																		(BgL_arg1662z00_273, BgL_list1665z00_276);
															}}
															BgL_arg1657z00_270 =
																MAKE_PAIR(BgL_arg1659z00_271,
																BgL_arg1660z00_272);
														}
														BgL_arg1655z00_269 =
															MAKE_PAIR(BgL_arg1657z00_270, BgL_defsz00_265);
													}
													{
														obj_t BgL_defsz00_506;

														obj_t BgL_varsz00_505;

														BgL_varsz00_505 = BgL_arg1654z00_268;
														BgL_defsz00_506 = BgL_arg1655z00_269;
														BgL_defsz00_265 = BgL_defsz00_506;
														BgL_varsz00_264 = BgL_varsz00_505;
														goto BgL_zc3anonymousza31652ze3z83_266;
													}
												}
										}
										{	/* Expand/assert.scm 63 */
											obj_t BgL_arg1672z00_284;

											{	/* Expand/assert.scm 63 */
												obj_t BgL_locz00_286;

												{	/* Expand/assert.scm 63 */
													obj_t BgL_locz00_312;

													BgL_locz00_312 =
														BGl_findzd2locationzd2zztools_locationz00
														(BgL_expz00_18);
													{	/* Expand/assert.scm 64 */
														bool_t BgL_testz00_508;

														if (STRUCTP(BgL_locz00_312))
															{	/* Expand/assert.scm 64 */
																BgL_testz00_508 =
																	(STRUCT_KEY(BgL_locz00_312) ==
																	CNST_TABLE_REF(((long) 7)));
															}
														else
															{	/* Expand/assert.scm 64 */
																BgL_testz00_508 = ((bool_t) 0);
															}
														if (BgL_testz00_508)
															{	/* Expand/assert.scm 64 */
																BgL_locz00_286 = BgL_locz00_312;
															}
														else
															{	/* Expand/assert.scm 64 */
																BgL_locz00_286 =
																	BGl_findzd2locationzd2zztools_locationz00
																	(BgL_predz00_247);
															}
													}
												}
												{	/* Expand/assert.scm 67 */
													obj_t BgL_arg1674z00_287;

													obj_t BgL_arg1675z00_288;

													BgL_arg1674z00_287 = CNST_TABLE_REF(((long) 8));
													{	/* Expand/assert.scm 67 */
														obj_t BgL_arg1676z00_289;

														obj_t BgL_arg1677z00_290;

														obj_t BgL_arg1678z00_291;

														{	/* Expand/assert.scm 67 */
															obj_t BgL_arg1688z00_296;

															obj_t BgL_arg1689z00_297;

															BgL_arg1688z00_296 = CNST_TABLE_REF(((long) 6));
															{	/* Expand/assert.scm 67 */
																obj_t BgL_list1690z00_298;

																BgL_list1690z00_298 = MAKE_PAIR(BNIL, BNIL);
																BgL_arg1689z00_297 =
																	BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																	(BgL_varsz00_19, BgL_list1690z00_298);
															}
															BgL_arg1676z00_289 =
																MAKE_PAIR(BgL_arg1688z00_296,
																BgL_arg1689z00_297);
														}
														{	/* Expand/assert.scm 68 */
															obj_t BgL_arg1691z00_299;

															obj_t BgL_arg1692z00_300;

															BgL_arg1691z00_299 = CNST_TABLE_REF(((long) 6));
															{	/* Expand/assert.scm 68 */
																obj_t BgL_arg1693z00_301;

																BgL_arg1693z00_301 =
																	MAKE_PAIR(CNST_TABLE_REF(((long) 4)),
																	BgL_oldzd2predzd2_248);
																{	/* Expand/assert.scm 68 */
																	obj_t BgL_list1695z00_303;

																	BgL_list1695z00_303 = MAKE_PAIR(BNIL, BNIL);
																	BgL_arg1692z00_300 =
																		BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																		(BgL_arg1693z00_301, BgL_list1695z00_303);
															}}
															BgL_arg1677z00_290 =
																MAKE_PAIR(BgL_arg1691z00_299,
																BgL_arg1692z00_300);
														}
														{	/* Expand/assert.scm 69 */
															bool_t BgL_testz00_526;

															if (STRUCTP(BgL_locz00_286))
																{	/* Expand/assert.scm 69 */
																	BgL_testz00_526 =
																		(STRUCT_KEY(BgL_locz00_286) ==
																		CNST_TABLE_REF(((long) 7)));
																}
															else
																{	/* Expand/assert.scm 69 */
																	BgL_testz00_526 = ((bool_t) 0);
																}
															if (BgL_testz00_526)
																{	/* Expand/assert.scm 70 */
																	obj_t BgL_arg1697z00_305;

																	obj_t BgL_arg1700z00_306;

																	BgL_arg1697z00_305 =
																		CNST_TABLE_REF(((long) 6));
																	{	/* Expand/assert.scm 70 */
																		obj_t BgL_arg1701z00_307;

																		BgL_arg1701z00_307 =
																			MAKE_PAIR
																			(BGl_locationzd2fullzd2fnamez00zztools_locationz00
																			(BgL_locz00_286),
																			STRUCT_REF(BgL_locz00_286,
																				(int) (((long) 1))));
																		{	/* Expand/assert.scm 70 */
																			obj_t BgL_list1703z00_309;

																			BgL_list1703z00_309 =
																				MAKE_PAIR(BNIL, BNIL);
																			BgL_arg1700z00_306 =
																				BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																				(BgL_arg1701z00_307,
																				BgL_list1703z00_309);
																	}}
																	BgL_arg1678z00_291 =
																		MAKE_PAIR(BgL_arg1697z00_305,
																		BgL_arg1700z00_306);
																}
															else
																{	/* Expand/assert.scm 69 */
																	BgL_arg1678z00_291 = BFALSE;
																}
														}
														{	/* Expand/assert.scm 67 */
															obj_t BgL_list1681z00_293;

															{	/* Expand/assert.scm 67 */
																obj_t BgL_arg1684z00_294;

																{	/* Expand/assert.scm 67 */
																	obj_t BgL_arg1685z00_295;

																	BgL_arg1685z00_295 = MAKE_PAIR(BNIL, BNIL);
																	BgL_arg1684z00_294 =
																		MAKE_PAIR(BgL_arg1678z00_291,
																		BgL_arg1685z00_295);
																}
																BgL_list1681z00_293 =
																	MAKE_PAIR(BgL_arg1677z00_290,
																	BgL_arg1684z00_294);
															}
															BgL_arg1675z00_288 =
																BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																(BgL_arg1676z00_289, BgL_list1681z00_293);
														}
													}
													BgL_arg1672z00_284 =
														MAKE_PAIR(BgL_arg1674z00_287, BgL_arg1675z00_288);
												}
											}
											BgL_arg1651z00_261 = MAKE_PAIR(BgL_arg1672z00_284, BNIL);
										}
										BgL_arg1647z00_259 =
											BGl_eappendzd22zd2zz__r4_pairs_and_lists_6_3z00
											(BgL_arg1650z00_260, BgL_arg1651z00_261);
									}
									BgL_arg1639z00_252 =
										MAKE_PAIR(BgL_arg1646z00_258, BgL_arg1647z00_259);
								}
								{	/* Expand/assert.scm 52 */
									obj_t BgL_list1641z00_254;

									{	/* Expand/assert.scm 52 */
										obj_t BgL_arg1643z00_255;

										{	/* Expand/assert.scm 52 */
											obj_t BgL_arg1644z00_256;

											BgL_arg1644z00_256 = MAKE_PAIR(BNIL, BNIL);
											BgL_arg1643z00_255 =
												MAKE_PAIR(BgL_arg1639z00_252, BgL_arg1644z00_256);
										}
										BgL_list1641z00_254 =
											MAKE_PAIR(BUNSPEC, BgL_arg1643z00_255);
									}
									BgL_arg1636z00_250 =
										BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
										(BgL_arg1637z00_251, BgL_list1641z00_254);
								}
							}
							return MAKE_PAIR(BgL_arg1635z00_249, BgL_arg1636z00_250);
						}
					}
				}
			}
		}
	}
Beispiel #8
0
SEXP attribute_hidden matchArgs(SEXP formals, SEXP supplied, SEXP call)
{
    int i, seendots, arg_i = 0;
    SEXP f, a, b, dots, actuals;

    actuals = R_NilValue;
    for (f = formals ; f != R_NilValue ; f = CDR(f), arg_i++) {
	/* CONS_NR is used since argument lists created here are only
	   used internally and so should not increment reference
	   counts */
	actuals = CONS_NR(R_MissingArg, actuals);
	SET_MISSING(actuals, 1);
    }
    /* We use fargused instead of ARGUSED/SET_ARGUSED on elements of
       formals to avoid modification of the formals SEXPs.  A gc can
       cause matchArgs to be called from finalizer code, resulting in
       another matchArgs call with the same formals.  In R-2.10.x, this
       corrupted the ARGUSED data of the formals and resulted in an
       incorrect "formal argument 'foo' matched by multiple actual
       arguments" error.
     */
    int fargused[arg_i ? arg_i : 1]; // avoid undefined behaviour
    memset(fargused, 0, sizeof(fargused));

    for(b = supplied; b != R_NilValue; b = CDR(b)) SET_ARGUSED(b, 0);

    PROTECT(actuals);

    /* First pass: exact matches by tag */
    /* Grab matched arguments and check */
    /* for multiple exact matches. */

    f = formals;
    a = actuals;
    arg_i = 0;
    while (f != R_NilValue) {
	if (TAG(f) != R_DotsSymbol) {
	    i = 1;
	    for (b = supplied; b != R_NilValue; b = CDR(b)) {
		if (TAG(b) != R_NilValue && pmatch(TAG(f), TAG(b), 1)) {
		    if (fargused[arg_i] == 2)
			error(_("formal argument \"%s\" matched by multiple actual arguments"),
			      CHAR(PRINTNAME(TAG(f))));
		    if (ARGUSED(b) == 2)
			error(_("argument %d matches multiple formal arguments"), i);
		    SETCAR(a, CAR(b));
		    if(CAR(b) != R_MissingArg) SET_MISSING(a, 0);
		    SET_ARGUSED(b, 2);
		    fargused[arg_i] = 2;
		}
		i++;
	    }
	}
	f = CDR(f);
	a = CDR(a);
        arg_i++;
    }

    /* Second pass: partial matches based on tags */
    /* An exact match is required after first ... */
    /* The location of the first ... is saved in "dots" */

    dots = R_NilValue;
    seendots = 0;
    f = formals;
    a = actuals;
    arg_i = 0;
    while (f != R_NilValue) {
	if (fargused[arg_i] == 0) {
	    if (TAG(f) == R_DotsSymbol && !seendots) {
		/* Record where ... value goes */
		dots = a;
		seendots = 1;
	    } else {
		i = 1;
		for (b = supplied; b != R_NilValue; b = CDR(b)) {
		    if (ARGUSED(b) != 2 && TAG(b) != R_NilValue &&
			pmatch(TAG(f), TAG(b), seendots)) {
			if (ARGUSED(b))
			    error(_("argument %d matches multiple formal arguments"), i);
			if (fargused[arg_i] == 1)
			    error(_("formal argument \"%s\" matched by multiple actual arguments"),
				  CHAR(PRINTNAME(TAG(f))));
			if (R_warn_partial_match_args) {
			    warningcall(call,
					_("partial argument match of '%s' to '%s'"),
					CHAR(PRINTNAME(TAG(b))),
					CHAR(PRINTNAME(TAG(f))) );
			}
			SETCAR(a, CAR(b));
			if (CAR(b) != R_MissingArg) SET_MISSING(a, 0);
			SET_ARGUSED(b, 1);
			fargused[arg_i] = 1;
		    }
		    i++;
		}
	    }
	}
	f = CDR(f);
	a = CDR(a);
        arg_i++;
    }

    /* Third pass: matches based on order */
    /* All args specified in tag=value form */
    /* have now been matched.  If we find ... */
    /* we gobble up all the remaining args. */
    /* Otherwise we bind untagged values in */
    /* order to any unmatched formals. */

    f = formals;
    a = actuals;
    b = supplied;
    seendots = 0;

    while (f != R_NilValue && b != R_NilValue && !seendots) {
	if (TAG(f) == R_DotsSymbol) {
	    /* Skip ... matching until all tags done */
	    seendots = 1;
	    f = CDR(f);
	    a = CDR(a);
	} else if (CAR(a) != R_MissingArg) {
	    /* Already matched by tag */
	    /* skip to next formal */
	    f = CDR(f);
	    a = CDR(a);
	} else if (ARGUSED(b) || TAG(b) != R_NilValue) {
	    /* This value used or tagged , skip to next value */
	    /* The second test above is needed because we */
	    /* shouldn't consider tagged values for positional */
	    /* matches. */
	    /* The formal being considered remains the same */
	    b = CDR(b);
	} else {
	    /* We have a positional match */
	    SETCAR(a, CAR(b));
	    if(CAR(b) != R_MissingArg) SET_MISSING(a, 0);
	    SET_ARGUSED(b, 1);
	    b = CDR(b);
	    f = CDR(f);
	    a = CDR(a);
	}
    }

    if (dots != R_NilValue) {
	/* Gobble up all unused actuals */
	SET_MISSING(dots, 0);
	i = 0;
	for(a = supplied; a != R_NilValue ; a = CDR(a)) if(!ARGUSED(a)) i++;

	if (i) {
	    a = allocList(i);
	    SET_TYPEOF(a, DOTSXP);
	    f = a;
	    for(b = supplied; b != R_NilValue; b = CDR(b))
		if(!ARGUSED(b)) {
		    SETCAR(f, CAR(b));
		    SET_TAG(f, TAG(b));
		    f = CDR(f);
		}
	    SETCAR(dots, a);
	}
    } else {
	/* Check that all arguments are used */
	SEXP unused = R_NilValue, last = R_NilValue;
	for (b = supplied; b != R_NilValue; b = CDR(b))
	    if (!ARGUSED(b)) {
		if(last == R_NilValue) {
		    PROTECT(unused = CONS(CAR(b), R_NilValue));
		    SET_TAG(unused, TAG(b));
		    last = unused;
		} else {
		    SETCDR(last, CONS(CAR(b), R_NilValue));
		    last = CDR(last);
		    SET_TAG(last, TAG(b));
		}
	    }

	if(last != R_NilValue) {
            /* show bad arguments in call without evaluating them */
            SEXP unusedForError = R_NilValue, last = R_NilValue;

            for(b = unused ; b != R_NilValue ; b = CDR(b)) {
                SEXP tagB = TAG(b), carB = CAR(b) ;
                if (TYPEOF(carB) == PROMSXP) carB = PREXPR(carB) ;
                if (last == R_NilValue) {
                    PROTECT(last = CONS(carB, R_NilValue));
                    SET_TAG(last, tagB);
                    unusedForError = last;
                } else {
                    SETCDR(last, CONS(carB, R_NilValue));
                    last = CDR(last);
                    SET_TAG(last, tagB);
                }
            }
	    errorcall(call /* R_GlobalContext->call */,
		      ngettext("unused argument %s",
			       "unused arguments %s",
			       (unsigned long) length(unusedForError)),
		      CHAR(STRING_ELT(deparse1line(unusedForError, 0), 0)) + 4);
                      /* '+ 4' is to remove 'list' from 'list(badTag1,...)' */
	}
    }
    UNPROTECT(1);
    return(actuals);
}
Beispiel #9
0
SEXP attribute_hidden matchUnnamedArgsCreateEnv(SEXP formals, SEXP supplied, SEXP call, SEXP rho, SEXP* outActuals)
{
    SEXP f, s;    
    SEXP actuals = PROTECT(supplied);
    SEXP newrho = PROTECT(NewEnvironmentNR(rho));
    SEXP prevS = R_NilValue;
    
    for (f = formals, s = supplied ; f != R_NilValue ; f = CDR(f), prevS = s, s = CDR(s)) {
        
        if (TAG(f) == R_DotsSymbol) {
            /* pack all arguments into ... */
            
            SEXP dots = CONS_NR(R_MissingArg, R_NilValue);
            SET_TAG(dots, R_DotsSymbol);
            if (prevS == R_NilValue) {
                UNPROTECT(1); /* old actuals */
                PROTECT(actuals = dots);
            } else {
                SETCDR(prevS, dots);
                ENABLE_REFCNT(prevS); /* dots are part of a protected list */
            }
            if (s != R_NilValue) {
                SET_TYPEOF(s, DOTSXP);
                SETCAR(dots, s);
                s = R_NilValue;
            } else {
                SET_MISSING(dots, 1);
            }
            prevS = dots;
            f = CDR(f);
            /* falls through into s == R_NilValue case */
        }
            
        if (s == R_NilValue) {
            /* fewer supplied arguments than formals */
            SEXP ds;
            for(; f != R_NilValue ; f = CDR(f), prevS = ds) { 
                ds = CONS_NR(R_MissingArg, R_NilValue);
                SET_TAG(ds, TAG(f));
                if (prevS == R_NilValue) {
                    UNPROTECT(1); /* old actuals */
                    PROTECT(actuals = ds);
                } else {
                    SETCDR(prevS, ds);
                    ENABLE_REFCNT(prevS); /* ds is part of a protected list */
                }
                SEXP fdefault = CAR(f);
                if (fdefault != R_MissingArg) {
                    SET_MISSING(ds, 2);
                    SETCAR(ds, mkPROMISEorConst(fdefault, newrho));
                } else {
                    SET_MISSING(ds, 1);
                }
            }
            break;
        }
        
        /* normal case, the next supplied arg is available */
        
        SET_TAG(s, TAG(f));
        if (CAR(s) == R_MissingArg) {
            SEXP fdefault = CAR(f);
            if (fdefault != R_MissingArg) {
                SET_MISSING(s, 2);
                SETCAR(s, mkPROMISEorConst(fdefault, newrho));
            } else {
                SET_MISSING(s, 1);
            }
        }
        if (prevS != R_NilValue) {
            ENABLE_REFCNT(prevS);
        }
    }

    if (s != R_NilValue) {
        /* some arguments are not used */
        SEXP unusedForError = PROTECT(s);
        SETCDR(prevS, R_NilValue); /* make sure they're not in the new environment */
            
        /* show bad arguments in call without evaluating them */
        for (; s != R_NilValue; s = CDR(s)) {
            SEXP carS = CAR(s);
            if (TYPEOF(carS) == PROMSXP) {
                SETCAR(s, PREXPR(carS));
            }
        }
        errorcall(call /* R_GlobalContext->call */,
	   ngettext("unused argument %s",
	     "unused arguments %s",
	     (unsigned long) length(unusedForError)),
	     CHAR(STRING_ELT(deparse1line(unusedForError, 0), 0)) + 4);
                  /* '+ 4' is to remove 'list' from 'list(badTag1,...)' */
        UNPROTECT(1);
    }
        
    if (prevS != R_NilValue) {
        ENABLE_REFCNT(prevS);
    }
    
    SET_FRAME(newrho, actuals);
    ENABLE_REFCNT(newrho);
    UNPROTECT(2); /* newrho, actuals */
    
    *outActuals = actuals;
    return(newrho);
}
Beispiel #10
0
void main_menu()
{
  image *Earth=cash.img(earth);
  image *Emap=cash.img(earth_mask);
	
  char name[20];
  ico_button *buts[MENU_TICONS];

  long maxx=0,maxy=0;
  int i=0;
  for (;i<MENU_TICONS;i++)
  {
    sprintf(name,"icon%04d.pcx",i*3+1);
    menu_icons[i*3]=cash.reg("art/icons.spe",name,SPEC_IMAGE,1);
    sprintf(name,"icon%04d.pcx",i*3+2);
    menu_icons[i*3+1]=cash.reg("art/icons.spe",name,SPEC_IMAGE,1);
    sprintf(name,"icon%04d.pcx",i*3+2);
    menu_icons[i*3+2]=cash.reg("art/icons.spe",name,SPEC_IMAGE,1);

    long x=WINDOW_FRAME_LEFT+(i%9)*cash.img(menu_icons[0])->width();
    long y=WINDOW_FRAME_TOP+(i/9)*cash.img(menu_icons[0])->height();
    if (x>maxx) maxx=x;
    if (y>maxy) maxy=y;
    buts[i]=new ico_button(x,y,menu_icons_ids[i],
			   menu_icons[i*3],menu_icons[i*3],
			   menu_icons[i*3+1],menu_icons[i*3+2],NULL);
  }

  buts[0]->next=buts[1];

  int b1,b2,b3,b4;
  
  if (DEFINEDP(symbol_value))
  {
    if (symbol_value(l_difficulty)==l_extreme)
    { b1=18; b2=10;  b3=12; b4=14;  }
    else if (symbol_value(l_difficulty)==l_hard)
    { b1=14; b2=18;  b3=10; b4=12;  }
    else if (symbol_value(l_difficulty)==l_easy)
    { b1=10; b2=12; b3=14; b4=18; }
    else 
    { b1=12; b2=14; b3=18; b4=10; }
  } else  
  { b1=12; b2=14; b3=18; b4=10; }
  

  buts[b1]->next=buts[b2];
  buts[b2]->next=buts[b3];
  buts[b3]->next=buts[b4];


  buts[1]->next=new ico_switch_button(buts[0]->X(),
				      buts[0]->Y()+cash.img(menu_icons[0])->height()*2,
				      ID_NULL, 
				      buts[b1],buts[17]);

 

  
  buts[17]->next=buts[8];

  buts[1]->set_xy(buts[0]->X(),
		  buts[0]->Y()+cash.img(menu_icons[0])->height()*1);
  buts[12]->set_xy(buts[0]->X(),
		  buts[0]->Y()+cash.img(menu_icons[0])->height()*2);
  buts[17]->set_xy(buts[0]->X(),
		  buts[0]->Y()+cash.img(menu_icons[0])->height()*3);
  buts[8]->set_xy(buts[0]->X(),
		  buts[0]->Y()+cash.img(menu_icons[0])->height()*4);



  ico_win=eh->new_window(-1,yres/2-80,-1,-1,buts[0],"Menu");
  
  
//  pmenu *main_pm=new pmenu(0,0,game_sub,screen,eh);
  time_marker old_time;

  screen->add_dirty(0,0,319,199);

  
  // create sphere map
  mask_line *p=make_mask_lines(Emap,Earth->width());

  int eoff=0,coff=0;
  event ev;
//  main_pm->draw(screen,eh,1);
  long x=84,y=60;
  Cell *v=find_symbol("earth_x");
  if (v && DEFINEDP(v)) x=lnumber_value(symbol_value(v));

  v=find_symbol("earth_y");
  if (v && DEFINEDP(v)) y=lnumber_value(symbol_value(v));
  int state=0,stop_menu=0;
  time_marker start;
  do
  {
    time_marker new_time;
    if (state || new_time.diff_time(&old_time)>0.15)
    {
      old_time.get_time();
      scan_map(screen,x,y,Earth,NULL,p,Emap->height(),eoff,coff);      
      if (state)
      { eoff+=8; coff+=4; }
      else
      {
        eoff+=2; coff+=1;
      }

      if (eoff>=320) eoff-=320;
      if (coff>=320) coff-=320;      
      eh->flush_screen();
    }

    if (eh->event_waiting())
    {
      eh->get_event(ev);    
      start.get_time();      // reset time till demo starts up

      menu_handler(ev,ico_win);
      if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button && ev.mouse_move.x>=x && ev.mouse_move.y>=y && 
	  ev.mouse_move.x<=x+Emap->width() && ev.mouse_move.y<=y+Emap->height())
      {
	state=1;
      } else if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button) state=0;

	
      
      eh->flush_screen();
    }

    if (new_time.diff_time(&start)>10)
    {
      if (!current_demo)
      {
	void *d=make_find_symbol("demos");
	if (DEFINEDP(d))	
	  current_demo=symbol_value(d);
      }
      if (current_demo)
      {
	if (set_demo_mode(DEMO_PLAY,lstring_value(CAR(current_demo)),eh))
	  stop_menu=1;
	current_demo=CDR(current_demo);
      }
    }
   
  } while (!stop_menu && 
	   (ev.type!=EV_MESSAGE || (ev.message.id!=ID_START_GAME && ev.message.id!=ID_QUIT)));

  for (i=0;i<MENU_TICONS;i++)
  {
    ifield *ic=ico_win->inm->unlink(menu_icons_ids[i]);
    if (i) delete ic;
    else delete buts[i];
  }
  
  eh->close_window(ico_win);
  for (int xx=0;xx<Emap->height();xx++)
    jfree(p[xx].remap);
  jfree(p);

  if (ev.message.id==ID_QUIT)   // propogate the quit message
    the_game->end_session();

//  delete main_pm;
}
Beispiel #11
0
Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
{
    unsigned result;
    Eterm reds_in = p->def_arg_reg[5];
    /*
     * Process is in the normal case scheduled out when reduction
     * count reach zero. When "save calls" is enabled reduction
     * count is subtracted with CONTEXT_REDS, i.e. initial reduction
     * count will be zero or less and process is scheduled out
     * when -CONTEXT_REDS is reached.
     *
     * HiPE does not support the "save calls" feature, so we switch
     * to using a positive reduction counter when executing in
     * hipe mode, but need to restore the "save calls" when
     * returning to beam. We also need to hide the save calls buffer
     * from BIFs. We do that by moving the saved calls buf to
     * suspended saved calls buf.
     *
     * Beam has initial reduction count in stored in p->def_arg_reg[5].
     *
     * Beam expects -neg_o_reds to be found in p->def_arg_reg[4]
     * on return to beam.
     */

    {
	struct saved_calls *scb = ERTS_PROC_SET_SAVED_CALLS_BUF(p, NULL);
	if (scb) {
	    reds_in += CONTEXT_REDS;
	    p->fcalls += CONTEXT_REDS;
	    ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, scb);
	}
    }

    p->flags |= F_HIPE_MODE; /* inform bifs where we are comming from... */

    p->i = NULL;
    /* Set current_function to undefined. stdlib hibernate tests rely on it. */
    p->current = NULL;

    DPRINTF("cmd == %#x (%s)", cmd, code_str(cmd));
    HIPE_CHECK_PCB(p);
    p->arity = 0;
    switch (cmd & 0xFF) {
      case HIPE_MODE_SWITCH_CMD_CALL: {
	  /* BEAM calls a native code function */
	  unsigned arity = cmd >> 8;

	  /* p->hipe.u.ncallee set in beam_emu */
	  if (p->cp == hipe_beam_pc_return) {
	    /* Native called BEAM, which now tailcalls native. */
	    hipe_pop_beam_trap_frame(p);
	    result = hipe_tailcall_to_native(p, arity, reg);
	    break;
	  }
	  DPRINTF("calling %#lx/%u", (long)p->hipe.u.ncallee, arity);
	  result = hipe_call_to_native(p, arity, reg);
	  break;
      }
      case HIPE_MODE_SWITCH_CMD_CALL_CLOSURE: {
	  /* BEAM calls a native code closure */
	  unsigned arity = cmd >> 8; /* #formals + #fvs (closure not counted) */
	  Eterm fun;
	  ErlFunThing *funp;

	  /* drop the fvs, move the closure, correct arity */
	  fun = reg[arity];
	  HIPE_ASSERT(is_fun(fun));
	  funp = (ErlFunThing*)fun_val(fun);
	  HIPE_ASSERT(funp->num_free <= arity);
	  arity -= funp->num_free;	/* arity == #formals */
	  reg[arity] = fun;
	  ++arity;	/* correct for having added the closure */
	  /* HIPE_ASSERT(p->hipe.u.ncallee == (void(*)(void))funp->native_address); */

	  /* just like a normal call from now on */

	  /* p->hipe.u.ncallee set in beam_emu */
	  if (p->cp == hipe_beam_pc_return) {
	      /* Native called BEAM, which now tailcalls native. */
	      hipe_pop_beam_trap_frame(p);
	      result = hipe_tailcall_to_native(p, arity, reg);
	      break;
	  }
	  DPRINTF("calling %#lx/%u", (long)p->hipe.u.ncallee, arity);
	  result = hipe_call_to_native(p, arity, reg);
	  break;
      }
      case HIPE_MODE_SWITCH_CMD_THROW: {
	  /* BEAM just executed hipe_beam_pc_throw[] */
	  /* Native called BEAM, which now throws an exception back to native. */
	  DPRINTF("beam throws freason %#lx fvalue %#lx", p->freason, p->fvalue);
	  hipe_pop_beam_trap_frame(p);
      do_throw_to_native:
	  p->def_arg_reg[0] = exception_tag[GET_EXC_CLASS(p->freason)];
	  hipe_find_handler(p);
	  result = hipe_throw_to_native(p);
	  break;
      }
      case HIPE_MODE_SWITCH_CMD_RETURN: {
	  /* BEAM just executed hipe_beam_pc_return[] */
	  /* Native called BEAM, which now returns back to native. */
	  /* pop trap frame off estack */
	  hipe_pop_beam_trap_frame(p);
	  p->def_arg_reg[0] = reg[0];
	  result = hipe_return_to_native(p);
	  break;
      }
    do_resume:
      case HIPE_MODE_SWITCH_CMD_RESUME: {
	  /* BEAM just executed hipe_beam_pc_resume[] */
	  /* BEAM called native, which suspended. */
	  if (p->flags & F_TIMO) {
	      /* XXX: The process will immediately execute 'clear_timeout',
		 repeating these two statements. Remove them? */
	      p->flags &= ~F_TIMO;
	      JOIN_MESSAGE(p);
	      p->def_arg_reg[0] = 0;	/* make_small(0)? */
	  } else
	      p->def_arg_reg[0] = 1;	/* make_small(1)? */
	  result = hipe_return_to_native(p);
	  break;
      }
      default:
	erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: cmd %#x\r\n", cmd);
    }
 do_return_from_native:
    DPRINTF("result == %#x (%s)", result, code_str(result));
    HIPE_CHECK_PCB(p);
    switch (result) {
      case HIPE_MODE_SWITCH_RES_RETURN: {
	  hipe_return_from_native(p);
	  reg[0] = p->def_arg_reg[0];
	  DPRINTF("returning with r(0) == %#lx", reg[0]);
	  break;
      }
      case HIPE_MODE_SWITCH_RES_THROW: {
	  DPRINTF("native throws freason %#lx fvalue %#lx", p->freason, p->fvalue);
	  hipe_throw_from_native(p);
	  break;
      }
      case HIPE_MODE_SWITCH_RES_TRAP: {
	  /*
	   * Native code called a BIF, which "failed" with a TRAP to BEAM.
	   * Prior to returning, the BIF stored (see BIF_TRAP<N>):

	   * the callee's address in p->i
	   * the callee's parameters in reg[0..2]
	   * the callee's arity in p->arity (for BEAM gc purposes)
	   *
	   * We need to remove the BIF's parameters from the native
	   * stack: to this end hipe_${ARCH}_glue.S stores the BIF's
	   * arity in p->hipe.narity.
	   *
	   * If the BIF emptied the stack (typically hibernate), p->hipe.nstack
	   * is NULL and there is no need to get rid of stacked parameters.
	   */
	  unsigned int i, is_recursive = 0;

          if (p->hipe.nstack != NULL) {
	      ASSERT(p->hipe.nsp != NULL);
	      is_recursive = hipe_trap_from_native_is_recursive(p);
          }
	  else {
	      /* Some architectures (risc) need this re-reset of nsp as the
	       * BIF wrapper do not detect stack change and causes an obsolete
	       * stack pointer to be saved in p->hipe.nsp before return to us.
	       */
	      p->hipe.nsp = NULL;
	  }

	  /* Schedule next process if current process was hibernated or is waiting
	     for messages */
	  if (p->flags & F_HIBERNATE_SCHED) {
	      p->flags &= ~F_HIBERNATE_SCHED;
	      goto do_schedule;
	  }

	  if (!(erts_smp_atomic32_read_acqb(&p->state) & ERTS_PSFLG_ACTIVE)) {
	      for (i = 0; i < p->arity; ++i)
		  p->arg_reg[i] = reg[i]; 	      
	      goto do_schedule;
	  }

	  if (is_recursive)
	      hipe_push_beam_trap_frame(p, reg, p->arity);
	  
	  result = HIPE_MODE_SWITCH_RES_CALL_BEAM;
	  break;
      }
      case HIPE_MODE_SWITCH_RES_CALL_EXPORTED: {
	  /* Native code calls or tailcalls BEAM.
	   *
	   * p->hipe.u.callee_exp is the callee's export entry
	   * p->arity is the callee's arity
	   * p->def_arg_reg[] contains the register parameters
	   * p->hipe.nsp[] contains the stacked parameters
	   */
	  if (hipe_call_from_native_is_recursive(p, reg)) {
	      /* BEAM called native, which now calls BEAM */
	      hipe_push_beam_trap_frame(p, reg, p->arity);
	  }
	  break;
      }
      case HIPE_MODE_SWITCH_RES_CALL_CLOSURE: {
	  /* Native code calls or tailcalls a closure in BEAM
	   *
	   * In native code a call to a closure of arity n looks like
	   * F(A1, ..., AN, Closure),
	   * The BEAM code for a closure expects to get:
	   * F(A1, ..., AN, FV1, ..., FVM, Closure)
	   *  (Where Ai is argument i and FVj is free variable j)
	   *
	   * p->hipe.u.closure contains the closure
	   * p->def_arg_reg[] contains the register parameters
	   * p->hipe.nsp[] contains the stacked parameters
	   */
	  ErlFunThing *closure;
	  unsigned num_free, arity, i, is_recursive;

	  HIPE_ASSERT(is_fun(p->hipe.u.closure));
	  closure = (ErlFunThing*)fun_val(p->hipe.u.closure);
	  num_free = closure->num_free;
	  arity = closure->fe->arity;

	  /* Store the arity in p->arity for the stack popping. */
	  /* Note: we already have the closure so only need to move arity
	     values to reg[]. However, there are arity+1 parameters in the
	     native code state that need to be removed. */
	  p->arity = arity+1; /* +1 for the closure */

	  /* Get parameters, don't do GC just yet. */
	  is_recursive = hipe_call_from_native_is_recursive(p, reg);

	  if ((Sint)closure->fe->address[-1] < 0) {
	      /* Unloaded. Let beam_emu.c:call_fun() deal with it. */
	      result = HIPE_MODE_SWITCH_RES_CALL_CLOSURE;
	  } else {
	      /* The BEAM code is present. Prepare to call it. */

	      /* Append the free vars after the actual parameters. */
	      for (i = 0; i < num_free; ++i)
		  reg[arity+i] = closure->env[i];

	      /* Update arity to reflect the new parameters. */
	      arity += i;

	      /* Make a call to the closure's BEAM code. */
	      p->i = closure->fe->address;

	      /* Change result code to the faster plain CALL type. */
	      result = HIPE_MODE_SWITCH_RES_CALL_BEAM;
	  }
	  /* Append the closure as the last parameter. Don't increment arity. */
	  reg[arity] = p->hipe.u.closure;

	  if (is_recursive) {
	      /* BEAM called native, which now calls BEAM.
		 Need to put a trap-frame on the beam stack.
		 This may cause GC, which is safe now that
		 the arguments, free vars, and most
		 importantly the closure, all are in reg[]. */
	      hipe_push_beam_trap_frame(p, reg, arity+1);
	  }
	  break;
      }
      case HIPE_MODE_SWITCH_RES_SUSPEND: {
	  p->i = hipe_beam_pc_resume;
	  p->arity = 0;
	  goto do_schedule;
      }
      case HIPE_MODE_SWITCH_RES_WAIT:
      case HIPE_MODE_SWITCH_RES_WAIT_TIMEOUT: {
	  /* same semantics, different debug trace messages */
#ifdef ERTS_SMP
	  /* XXX: BEAM has different entries for the locked and unlocked
	     cases. HiPE doesn't, so we must check dynamically. */
	  if (p->hipe_smp.have_receive_locks)
	      p->hipe_smp.have_receive_locks = 0;
	  else
	      erts_smp_proc_lock(p, ERTS_PROC_LOCKS_MSG_RECEIVE);
#endif
	  p->i = hipe_beam_pc_resume;
	  p->arity = 0;
	  erts_smp_atomic32_read_band_relb(&p->state,
					   ~ERTS_PSFLG_ACTIVE);
	  erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_MSG_RECEIVE);
      do_schedule:
	  {
	      struct saved_calls *scb;

	      scb = ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, NULL);
	      if (scb)
		  ERTS_PROC_SET_SAVED_CALLS_BUF(p, scb);

              /* The process may have died while it was executing,
                 if so we return out from native code to the interpreter */
              if (erts_smp_atomic32_read_nob(&p->state) & ERTS_PSFLG_EXITING)
                  p->i = beam_exit;
#ifdef DEBUG
	      ASSERT(p->debug_reds_in == reds_in);
#endif
	      p->flags &= ~F_HIPE_MODE;

	      ERTS_SMP_UNREQ_PROC_MAIN_LOCK(p);
	      p = erts_schedule(NULL, p, reds_in - p->fcalls);
	      ERTS_SMP_REQ_PROC_MAIN_LOCK(p);
	      ASSERT(!(p->flags & F_HIPE_MODE));
#ifdef ERTS_SMP
	      p->hipe_smp.have_receive_locks = 0;
	      reg = p->scheduler_data->x_reg_array;
#endif
	  }
	  {
	      Eterm *argp;
	      int i;
	  
	      argp = p->arg_reg;
	      for (i = p->arity; --i >= 0;)
		  reg[i] = argp[i];
	  }
	  {
	      struct saved_calls *scb;

	      reds_in = p->fcalls;
	      p->def_arg_reg[5] = reds_in;
#ifdef DEBUG
	      p->debug_reds_in = reds_in;
#endif
	      if (p->i == hipe_beam_pc_resume) {
		  p->flags |= F_HIPE_MODE; /* inform bifs where we are comming from... */
		  scb = ERTS_PROC_SET_SAVED_CALLS_BUF(p, NULL);
		  if (scb)
		      ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, scb);
		  p->i = NULL;
		  p->arity = 0;
		  goto do_resume;
	      }

	      scb = ERTS_PROC_GET_SAVED_CALLS_BUF(p);
	      if (!scb)
		  p->def_arg_reg[4] = 0;
	      else {
		  p->def_arg_reg[4] = CONTEXT_REDS;
		  p->fcalls = -CONTEXT_REDS + reds_in;
	      }
	  }

	  HIPE_CHECK_PCB(p);
	  result = HIPE_MODE_SWITCH_RES_CALL_BEAM;
	  p->def_arg_reg[3] = result;
	  return p;
      }
      case HIPE_MODE_SWITCH_RES_APPLY: {
	  Eterm mfa[3], args;
	  unsigned int arity;
	  void *address;

	  hipe_pop_params(p, 3, &mfa[0]);

	  /* Unroll the arglist onto reg[]. */
	  args = mfa[2];
	  arity = 0;
	  while (is_list(args)) {
	      if (arity < 255) {
		  reg[arity++] = CAR(list_val(args));
		  args = CDR(list_val(args));
	      } else
		  goto do_apply_fail;
	  }
	  if (is_not_nil(args))
	      goto do_apply_fail;

	  /* find a native code entry point for {M,F,A} for a remote call */
	  address = hipe_get_remote_na(mfa[0], mfa[1], arity);
	  if (!address)
		  goto do_apply_fail;
	  p->hipe.u.ncallee = (void(*)(void)) address;
	  result = hipe_tailcall_to_native(p, arity, reg);
	  goto do_return_from_native;
      do_apply_fail:
	  p->freason = BADARG;
	  goto do_throw_to_native;
      }
      default:
	erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: result %#x\r\n", result);
    }

    {
	struct saved_calls *scb = ERTS_PROC_SET_SUSPENDED_SAVED_CALLS_BUF(p, NULL);
	if (!scb)
	    p->def_arg_reg[4] = 0;
	else {
	    p->def_arg_reg[4] = CONTEXT_REDS;
	    p->fcalls -= CONTEXT_REDS;
	    ERTS_PROC_SET_SAVED_CALLS_BUF(p, scb);
	}
    }

    HIPE_CHECK_PCB(p);
    p->def_arg_reg[3] = result;
#if NR_ARG_REGS > 5
    /*
     * When NR_ARG_REGS > 5, we need to protect the process' input
     * reduction count (which BEAM stores in def_arg_reg[5]) from
     * being clobbered by the arch glue code.
     */
    p->def_arg_reg[5] = reds_in;
#endif
    p->flags &= ~F_HIPE_MODE;
    return p;
}
Beispiel #12
0
int menu(void *args, JCFont *font)             // reurns -1 on esc
{
  main_menu();
  char *title=NULL;
  if (!NILP(CAR(args)))
    title=lstring_value(CAR(args));
  Cell *def=lcar(lcdr(lcdr(args)));
  args=CAR(CDR(args));

  int options=list_length(args);
  int mh=(font->height()+1)*options+10,maxw=0;

  Cell *c=(Cell *)args;
  for (;!NILP(c);c=CDR(c))
  {
    if (strlen(men_str(CAR(c)))>maxw)
      maxw=strlen(men_str(CAR(c)));
  }
  
  int mw=(font->width())*maxw+20;
  int mx=screen->width()/2-mw/2,
      my=screen->height()/2-mh/2;
  

  screen->add_dirty(mx,my,mx+mw-1,my+mh-1);

  if (title)
  {
    int tl=strlen(title)*font->width();
    int tx=screen->width()/2-tl/2;
    dark_wiget(tx-2,my-font->height()-4,tx+tl+2,my-2,eh->medium_color(),eh->dark_color(),180);
    font->put_string(screen,tx+1,my-font->height()-2,title,eh->bright_color());
  }
  
  dark_wiget(mx,my,mx+mw-1,my+mh-1,eh->medium_color(),eh->dark_color(),200);


  int y=my+5;
  for (c=(Cell *)args;!NILP(c);c=CDR(c))
  {
    char *ms=men_str(CAR(c));
    font->put_string(screen,mx+10+1,y+1,ms,eh->black());
    font->put_string(screen,mx+10,y,ms,eh->bright_color());
    y+=font->height()+1;
  }
  

  eh->flush_screen();
  event ev;
  int choice=0,done=0;
  int bh=font->height()+3;
  image *save=new image(mw-2,bh);
  int color=128,cdir=50;
  
  time_marker *last_color_time=NULL; 
  if (!NILP(def))
    choice=lnumber_value(def);
  do
  {
  
    if (eh->event_waiting())
    {
      eh->get_event(ev);
      if (ev.type==EV_KEY)
      {
	switch (ev.key)
	{
	  case JK_ESC : 
	  { choice=-1; done=1; } break;
	  case JK_ENTER :
	  { done=1; } break;
	  case JK_DOWN : 
	  { if (choice<options-1) 
	    choice++;
	  else choice=0;
	  } break;
	  case JK_UP :
	  {
	    if (choice>0)
	    choice--;
	    else choice=options-1;
	  } break;		      
	}
      } else if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
      {
	if (ev.mouse_move.x>mx && ev.mouse_move.x<mx+mw && ev.mouse_move.y>my &&
	    ev.mouse_move.y<my+mh)
	{
	  int msel=(ev.mouse_move.y-my)/(font->height()+1);
	  if (msel>=options) msel=options-1;
	  if (msel==choice)                    // clicked on already selected item, return it
	    done=1;
	  else choice=msel;                    // selects an item
	}
      }
      eh->flush_screen();
    }

    time_marker cur_time;
    if (!last_color_time || (int)(cur_time.diff_time(last_color_time)*1000)>120)
    {       
      if (last_color_time)
        delete last_color_time;
      last_color_time=new time_marker;

      int by1=(font->height()+1)*choice+my+5-2;
      int by2=by1+bh-1;

      screen->put_part(save,0,0,mx+1,by1,mx+mw-2,by2);
      tint_area(mx+1,by1,mx+mw-2,by2,63,63,63,color);

      char *cur=men_str(nth(choice,args));
      font->put_string(screen,mx+10+1,by1+3,cur,eh->black());
      font->put_string(screen,mx+10,by1+2,cur,eh->bright_color());
      screen->rectangle(mx+1,by1,mx+mw-2,by2,eh->bright_color());

      color+=cdir;

      if (color<12 || color>256)
      {
	cdir=-cdir;
	color+=cdir;
      }
      eh->flush_screen();
      save->put_image(screen,mx+1,by1);
    } else milli_wait(10);

  } while (!done);
  if (last_color_time)
    delete last_color_time;
  delete save;
  the_game->draw(the_game->state==SCENE_STATE);

  if (choice!=-1)
  {
    void *val=nth(choice,args);
    if (item_type(val)==L_CONS_CELL)   // is there another value that the user want us to return?
      return lnumber_value(lcdr(val));  
  }
  return choice;
}
Beispiel #13
0
static int subtract_set_finish(Process *p, ErtsSubtractContext *context) {
    const Sint CHECKS_PER_RED = 8;
    Sint checks, budget;

    budget = CHECKS_PER_RED * ERTS_BIF_REDS_LEFT(p);
    checks = 0;

#ifdef DEBUG
    budget = budget / 10 + 1;
#endif

    while (checks < budget && is_list(context->iterator)) {
        subtract_tree_t *node;
        const Eterm *cell;
        Eterm value, next;

        cell = list_val(context->iterator);
        value = CAR(cell);
        next = CDR(cell);

        ASSERT(context->rhs_remaining > 0);

        node = subtract_rbt_lookup(context->u.rhs_set.tree, value);

        if (node == NULL) {
            Eterm *hp = HAllocX(p, 2, context->lhs_remaining * 2);

            *context->result_cdr = make_list(hp);
            context->result_cdr = &CDR(hp);

            CAR(hp) = value;
        } else {
            if (context->rhs_remaining-- == 1) {
                *context->result_cdr = next;

                BUMP_REDS(p, checks / CHECKS_PER_RED);

                return 1;
            }

            if (node->count-- == 1) {
                subtract_rbt_delete(&context->u.rhs_set.tree, node);
            }
        }

        context->iterator = next;
        context->lhs_remaining--;
        checks++;
    }

    *context->result_cdr = NIL;

    BUMP_REDS(p, checks / CHECKS_PER_RED);

    if (is_list(context->iterator)) {
        ASSERT(context->lhs_remaining > 0 && context->rhs_remaining > 0);
        return 0;
    }

    return 1;
}
Beispiel #14
0
static int subtract_naive_rhs(Process *p, ErtsSubtractContext *context) {
    const Sint CHECKS_PER_RED = 16;
    Sint checks, budget;

    budget = CHECKS_PER_RED * ERTS_BIF_REDS_LEFT(p);
    checks = 0;

#ifdef DEBUG
    budget = budget / 10 + 1;
#endif

    while (checks < budget && is_list(context->iterator)) {
        const Eterm *cell;
        Eterm value, next;
        int found_at;

        cell = list_val(context->iterator);
        value = CAR(cell);
        next = CDR(cell);

        for (found_at = context->rhs_remaining - 1; found_at >= 0; found_at--) {
            if (EQ(value, context->u.rhs_elements[found_at])) {
                break;
            }
        }

        if (found_at < 0) {
            /* Destructively add the value to the result. This is safe
             * since the GC is disabled and the unfinished term is never
             * leaked to the outside world. */
            Eterm *hp = HAllocX(p, 2, context->lhs_remaining * 2);

            *context->result_cdr = make_list(hp);
            context->result_cdr = &CDR(hp);

            CAR(hp) = value;
        } else if (found_at >= 0) {
            Eterm swap;

            if (context->rhs_remaining-- == 1) {
                /* We've run out of items to remove, so the rest of the
                 * result will be equal to the remainder of the input. We know
                 * that LHS is well-formed as any errors would've been reported
                 * during length determination. */
                *context->result_cdr = next;

                BUMP_REDS(p, MIN(budget, checks) / CHECKS_PER_RED);

                return 1;
            }

            swap = context->u.rhs_elements[context->rhs_remaining];
            context->u.rhs_elements[found_at] = swap;
        }

        checks += context->rhs_remaining;
        context->iterator = next;
        context->lhs_remaining--;
    }

    /* The result only has to be terminated when returning it to the user, but
     * we're doing it when trapping as well to prevent headaches when
     * debugging. */
    *context->result_cdr = NIL;

    BUMP_REDS(p, MIN(budget, checks) / CHECKS_PER_RED);

    if (is_list(context->iterator)) {
        ASSERT(context->lhs_remaining > 0 && context->rhs_remaining > 0);
        return 0;
    }

    return 1;
}
Beispiel #15
0
static R_size_t objectsize(SEXP s)
{
    int i;
    R_size_t cnt = 0, vcnt = 0;
    SEXP tmp, dup;
    Rboolean isVec = FALSE;

    switch (TYPEOF(s)) {
    case NILSXP:
	return(0);
	break;
    case SYMSXP:
	break;
    case LISTSXP:
    case LANGSXP:
    case BCODESXP:
	cnt += objectsize(TAG(s));
	cnt += objectsize(CAR(s));
	cnt += objectsize(CDR(s));
	break;
    case CLOSXP:
	cnt += objectsize(FORMALS(s));
	cnt += objectsize(BODY(s));
	/* no charge for the environment */
	break;
    case ENVSXP:
    case PROMSXP:
    case SPECIALSXP:
    case BUILTINSXP:
	break;
    case CHARSXP:
	vcnt = BYTE2VEC(length(s)+1);
	isVec = TRUE;
	break;
    case LGLSXP:
    case INTSXP:
	vcnt = INT2VEC(length(s));
	isVec = TRUE;
	break;
    case REALSXP:
	vcnt = FLOAT2VEC(length(s));
	isVec = TRUE;
	break;
    case CPLXSXP:
	vcnt = COMPLEX2VEC(length(s));
	isVec = TRUE;
	break;
    case STRSXP:
	vcnt = PTR2VEC(length(s));
	dup = csduplicated(s);
	for (i = 0; i < length(s); i++) {
	    tmp = STRING_ELT(s, i);
	    if(tmp != NA_STRING && !LOGICAL(dup)[i])
		cnt += objectsize(tmp);
	}
	isVec = TRUE;
	break;
    case DOTSXP:
    case ANYSXP:
	/* we don't know about these */
	break;
    case VECSXP:
    case EXPRSXP:
    case WEAKREFSXP:
	/* Generic Vector Objects */
	vcnt = PTR2VEC(length(s));
	for (i = 0; i < length(s); i++)
	    cnt += objectsize(VECTOR_ELT(s, i));
	isVec = TRUE;
	break;
    case EXTPTRSXP:
	cnt += sizeof(void *);  /* the actual pointer */
	cnt += objectsize(EXTPTR_PROT(s));
	cnt += objectsize(EXTPTR_TAG(s));
	break;
    case RAWSXP:
	vcnt = BYTE2VEC(length(s));
	isVec = TRUE;
	break;
    case S4SXP:
	/* Has TAG and ATRIB but no CAR nor CDR */
	cnt += objectsize(TAG(s));
	break;
    default:
	UNIMPLEMENTED_TYPE("object.size", s);
    }
    /* add in node space:
       we need to take into account the rounding up that goes on
       in the node classes. */
    if(isVec) {
	cnt += sizeof(SEXPREC_ALIGN);
	if (vcnt > 16) cnt += 8*vcnt;
	else if (vcnt > 8) cnt += 128;
	else if (vcnt > 6) cnt += 64;
	else if (vcnt > 4) cnt += 48;
	else if (vcnt > 2) cnt += 32;
	else if (vcnt > 1) cnt += 16;
	else if (vcnt > 0) cnt += 8;
    } else cnt += sizeof(SEXPREC);
    /* add in attributes: these are fake for CHARXPs */
    if(TYPEOF(s) != CHARSXP) cnt += objectsize(ATTRIB(s));
    return(cnt);
}
Beispiel #16
0
SEXP attribute_hidden matchPositionalArgsCreateEnv(SEXP formals, SEXP *supplied, int nsupplied, SEXP call, SEXP rho, SEXP* outActuals)
{
    SEXP *s;
    SEXP f, a;    
    SEXP actuals = R_NilValue;
    
    SEXP newrho = PROTECT(NewEnvironmentNR(rho));    
    
    SEXP *endSupplied = supplied + nsupplied;
    for (f = formals, s = supplied, a = actuals ; f != R_NilValue ; f = CDR(f), s++) {
    
        if (TAG(f) == R_DotsSymbol) {
            /* pack all remaining arguments into ... */
            
            SEXP *rs = endSupplied - 1;
            SEXP dotsContent = R_NilValue;
            for(; rs >= s; rs--) {
                dotsContent = CONS(*rs, dotsContent); /* FIXME: enabling refcnt? */
            }
            SEXP dots = CONS_NR(dotsContent, R_NilValue);
            SET_TAG(dots, R_DotsSymbol);
            if (dotsContent != R_NilValue) {
                SET_TYPEOF(dotsContent, DOTSXP);
            } else {
                SET_MISSING(dots, 1);
            }
            if (a == R_NilValue) {
                PROTECT(actuals = dots);
            } else {
                SETCDR(a, dots);
                ENABLE_REFCNT(a); /* dots are part of a protected list */
            }
            a = dots;
            f = CDR(f);
            s = endSupplied;
            /* falls through into noMoreSupplied branch below */
        }
            
        if (s == endSupplied) {
            /* possibly fewer supplied arguments than formals */
            SEXP ds;
            for(; f != R_NilValue ; f = CDR(f), a = ds) { 
                ds = CONS_NR(R_MissingArg, R_NilValue);
                SET_TAG(ds, TAG(f));
                if (a == R_NilValue) {
                    PROTECT(actuals = ds);
                } else {
                    SETCDR(a, ds);
                    ENABLE_REFCNT(a); /* ds is part of a protected list */
                }
                SEXP fdefault = CAR(f);
                if (fdefault != R_MissingArg) {
                    SET_MISSING(ds, 2);
                    SETCAR(ds, mkPROMISEorConst(fdefault, newrho));
                } else {
                    SET_MISSING(ds, 1);
                }
            }
            break;
        }
        
        /* normal case, the next supplied arg is available */
        
        SEXP arg = CONS_NR(*s, R_NilValue);
        SET_TAG(arg, TAG(f));

        if (a == R_NilValue) {
            PROTECT(actuals = arg);
        } else {
            SETCDR(a, arg);
            ENABLE_REFCNT(a);
        }
        a = arg;
    }

    if (s < endSupplied) {
        /* some arguments are not used */

        SEXP *rs = endSupplied - 1;
        SEXP unusedForError = R_NilValue;
        for(; rs >= s; rs--) {
            SEXP rsValue = *rs;
            if (TYPEOF(rsValue) == PROMSXP) {
                rsValue = PREXPR(rsValue);
            }
            unusedForError = CONS(rsValue, unusedForError);
        }
        PROTECT(unusedForError); /* needed? */
        errorcall(call /* R_GlobalContext->call */,
	   ngettext("unused argument %s",
	     "unused arguments %s",
	     (unsigned long) length(unusedForError)),
	     CHAR(STRING_ELT(deparse1line(unusedForError, 0), 0)) + 4);
                  /* '+ 4' is to remove 'list' from 'list(badTag1,...)' */
        UNPROTECT(1);
    }
        
    if (a != R_NilValue) {
        ENABLE_REFCNT(a);
    }
    
    SET_FRAME(newrho, actuals);
    ENABLE_REFCNT(newrho);
    UNPROTECT(1);  /* newrho */
    if (actuals != R_NilValue) {
        UNPROTECT(1); /* actuals */
    }    
    *outActuals = actuals;
    
    return(newrho);
}
Beispiel #17
0
bool CRInterface::run_r_helper(CSGInterface* from_if)
{
	char* rfile=NULL;

	try
	{
		for (int i=0; i<from_if->get_nrhs(); i++)
		{
			int len=0;
			char* var_name = from_if->get_string(len);
			from_if->SG_DEBUG("var_name = '%s'\n", var_name);
			if (strmatch(var_name, "rfile"))
			{
				len=0;
				rfile=from_if->get_string(len);
				from_if->SG_DEBUG("rfile = '%s'\n", rfile);
				break;
			}
			else
			{
				CRInterface* in = new CRInterface(R_NilValue, false);
				in->create_return_values(1);
				from_if->translate_arg(from_if, in);

				setVar(install(var_name), in->get_return_values(), R_GlobalEnv);
				delete[] var_name;
				SG_UNREF(in);
			}
		}
	}
	catch (ShogunException e)
	{
		from_if->SG_PRINT("%s", e.get_exception_string());
		return true;
	}
	
	// Find source function
	SEXP src = Rf_findFun(Rf_install("source"), R_GlobalEnv);
	PROTECT(src);

	// Make file argument
	SEXP file;
	PROTECT(file = NEW_CHARACTER(1));
	SET_STRING_ELT(file, 0, COPY_TO_USER_STRING(rfile));

	// expression source(file,print.eval=p)
	SEXP expr;
	PROTECT(expr = allocVector(LANGSXP,2));
	SETCAR(expr,src); 
	SETCAR(CDR(expr),file);

	int err=0;
	R_tryEval(expr,NULL,&err);

	if (err)
	{
		UNPROTECT(3);
		from_if->SG_PRINT("Error occurred\n");
		return true;
	}

	SEXP results;
	PROTECT(results=findVar(install("results"), R_GlobalEnv));
	from_if->SG_DEBUG("Found type %d\n", TYPEOF(results));

	try
	{
		if (TYPEOF(results)==LISTSXP)
		{
			int32_t sz=Rf_length(results);
			from_if->SG_DEBUG("Found %d args\n", sz);

			if (sz>0 && from_if->create_return_values(sz))
			{
				CRInterface* out = new CRInterface(results, false);

				//process d
				for (int32_t i=0; i<sz; i++)
					from_if->translate_arg(out, from_if);

				SG_UNREF(out);
			}
			else if (sz!=from_if->get_nlhs())
			{
				UNPROTECT(4);
				from_if->SG_PRINT("Number of return values (%d) does not match "
						"number of expected return values (%d).\n",
						sz, from_if->get_nlhs());
				return true;
			}
		}
	}
	catch (ShogunException e)
	{
		UNPROTECT(4);
		from_if->SG_PRINT("%s", e.get_exception_string());
	}

	UNPROTECT(4);

	return true;
}
Beispiel #18
0
SEXP attribute_hidden do_sys(SEXP call, SEXP op, SEXP args, SEXP rho)
{
    int i, n  = -1, nframe;
    SEXP rval, t;
    RCNTXT *cptr;

    checkArity(op, args);
    /* first find the context that sys.xxx needs to be evaluated in */
    cptr = R_GlobalContext;
    t = cptr->sysparent;
    while (cptr != R_ToplevelContext) {
	if (cptr->callflag & CTXT_FUNCTION )
	    if (cptr->cloenv == t)
		break;
	cptr = cptr->nextcontext;
    }

    if (length(args) == 1) n = asInteger(CAR(args));

    switch (PRIMVAL(op)) {
    case 1: /* parent */
	if(n == NA_INTEGER)
	    error(_("invalid '%s' argument"), "n");
	i = nframe = framedepth(cptr);
	/* This is a pretty awful kludge, but the alternative would be
	   a major redesign of everything... -pd */
	while (n-- > 0)
	    i = R_sysparent(nframe - i + 1, cptr);
	return ScalarInteger(i);
    case 2: /* call */
	if(n == NA_INTEGER)
	    error(_("invalid '%s' argument"), "which");
	return R_syscall(n, cptr);
    case 3: /* frame */
	if(n == NA_INTEGER)
	    error(_("invalid '%s' argument"), "which");
	return R_sysframe(n, cptr);
    case 4: /* sys.nframe */
	return ScalarInteger(framedepth(cptr));
    case 5: /* sys.calls */
	nframe = framedepth(cptr);
	PROTECT(rval = allocList(nframe));
	t=rval;
	for(i = 1; i <= nframe; i++, t = CDR(t))
	    SETCAR(t, R_syscall(i, cptr));
	UNPROTECT(1);
	return rval;
    case 6: /* sys.frames */
	nframe = framedepth(cptr);
	PROTECT(rval = allocList(nframe));
	t = rval;
	for(i = 1; i <= nframe; i++, t = CDR(t))
	    SETCAR(t, R_sysframe(i, cptr));
	UNPROTECT(1);
	return rval;
    case 7: /* sys.on.exit */
	if( R_GlobalContext->nextcontext != NULL)
	    return R_GlobalContext->nextcontext->conexit;
	else
	    return R_NilValue;
    case 8: /* sys.parents */
	nframe = framedepth(cptr);
	rval = allocVector(INTSXP, nframe);
	for(i = 0; i < nframe; i++)
	    INTEGER(rval)[i] = R_sysparent(nframe - i, cptr);
	return rval;
    case 9: /* sys.function */
	if(n == NA_INTEGER)
	    error(_("invalid '%s' value"), "which");
	return(R_sysfunction(n, cptr));
    default:
	error(_("internal error in 'do_sys'"));
	return R_NilValue;/* just for -Wall */
    }
}
Beispiel #19
0
/* expand-assert */
	BGL_EXPORTED_DEF obj_t BGl_expandzd2assertzd2zzexpand_assertz00(obj_t
		BgL_xz00_15, obj_t BgL_ez00_16)
	{
		AN_OBJECT;
		{	/* Expand/assert.scm 26 */
			{
				obj_t BgL_varsz00_205;

				obj_t BgL_predz00_206;

				obj_t BgL_varsz00_202;

				obj_t BgL_bodyz00_203;

				if (PAIRP(BgL_xz00_15))
					{	/* Expand/assert.scm 27 */
						obj_t BgL_cdrzd21399zd2_211;

						BgL_cdrzd21399zd2_211 = CDR(BgL_xz00_15);
						if (PAIRP(BgL_cdrzd21399zd2_211))
							{	/* Expand/assert.scm 27 */
								obj_t BgL_cdrzd21403zd2_213;

								BgL_cdrzd21403zd2_213 = CDR(BgL_cdrzd21399zd2_211);
								if ((CAR(BgL_cdrzd21399zd2_211) == CNST_TABLE_REF(((long) 2))))
									{	/* Expand/assert.scm 27 */
										if (PAIRP(BgL_cdrzd21403zd2_213))
											{	/* Expand/assert.scm 27 */
												obj_t BgL_carzd21406zd2_216;

												BgL_carzd21406zd2_216 = CAR(BgL_cdrzd21403zd2_213);
												if (PAIRP(BgL_carzd21406zd2_216))
													{	/* Expand/assert.scm 27 */
														BgL_varsz00_202 = BgL_carzd21406zd2_216;
														BgL_bodyz00_203 = CDR(BgL_cdrzd21403zd2_213);
														{	/* Expand/assert.scm 30 */
															obj_t BgL_newz00_233;

															{	/* Expand/assert.scm 30 */
																obj_t BgL_arg1623z00_234;

																obj_t BgL_arg1624z00_235;

																BgL_arg1623z00_234 = CNST_TABLE_REF(((long) 0));
																{	/* Expand/assert.scm 30 */
																	obj_t BgL_arg1625z00_236;

																	BgL_arg1625z00_236 =
																		BGl_eappendzd22zd2zz__r4_pairs_and_lists_6_3z00
																		(BgL_bodyz00_203, BNIL);
																	{	/* Expand/assert.scm 30 */
																		obj_t BgL_list1626z00_237;

																		BgL_list1626z00_237 =
																			MAKE_PAIR(BgL_arg1625z00_236, BNIL);
																		BgL_arg1624z00_235 =
																			BGl_consza2za2zz__r4_pairs_and_lists_6_3z00
																			(BgL_varsz00_202, BgL_list1626z00_237);
																}}
																BgL_newz00_233 =
																	MAKE_PAIR(BgL_arg1623z00_234,
																	BgL_arg1624z00_235);
															}
															BGl_replacez12z12zztools_miscz00(BgL_xz00_15,
																BgL_newz00_233);
															return PROCEDURE_ENTRY(BgL_ez00_16) (BgL_ez00_16,
																BgL_xz00_15, BgL_ez00_16, BEOA);
														}
													}
												else
													{	/* Expand/assert.scm 27 */
														obj_t BgL_carzd21419zd2_220;

														BgL_carzd21419zd2_220 = CAR(BgL_cdrzd21399zd2_211);
														if (BGl_listzf3zf3zz__r4_pairs_and_lists_6_3z00
															(BgL_carzd21419zd2_220))
															{	/* Expand/assert.scm 27 */
																BgL_varsz00_205 = BgL_carzd21419zd2_220;
																BgL_predz00_206 = CDR(BgL_cdrzd21399zd2_211);
															BgL_tagzd21390zd2_207:
																{	/* Expand/assert.scm 34 */
																	bool_t BgL_testz00_446;

																	{	/* Expand/assert.scm 34 */
																		bool_t BgL_testz00_447;

																		if (INTEGERP
																			(BGl_za2compilerzd2debugza2zd2zzengine_paramz00))
																			{	/* Expand/assert.scm 34 */
																				BgL_testz00_447 =
																					(
																					(long)
																					CINT
																					(BGl_za2compilerzd2debugza2zd2zzengine_paramz00)
																					>= ((long) 1));
																			}
																		else
																			{	/* Expand/assert.scm 34 */
																				BgL_testz00_447 = ((bool_t) 0);
																			}
																		if (BgL_testz00_447)
																			{	/* Expand/assert.scm 34 */
																				BgL_testz00_446 = ((bool_t) 1);
																			}
																		else
																			{	/* Expand/assert.scm 35 */
																				obj_t BgL__andtest_1594z00_241;

																				{	/* Expand/assert.scm 35 */
																					obj_t BgL_arg1630z00_243;

																					obj_t BgL_arg1631z00_244;

																					BgL_arg1630z00_243 =
																						CNST_TABLE_REF(((long) 1));
																					{	/* Expand/assert.scm 35 */
																						obj_t BgL_arg1632z00_245;

																						BgL_arg1632z00_245 =
																							BGl_thezd2backendzd2zzbackend_backendz00
																							();
																						{
																							BgL_backendz00_bglt
																								BgL_auxz00_454;
																							BgL_auxz00_454 =
																								(BgL_backendz00_bglt)
																								(BgL_arg1632z00_245);
																							BgL_arg1631z00_244 =
																								(((BgL_backendz00_bglt)
																									CREF(BgL_auxz00_454))->
																								BgL_debugzd2supportzd2);
																					}}
																					BgL__andtest_1594z00_241 =
																						BGl_memqz00zz__r4_pairs_and_lists_6_3z00
																						(BgL_arg1630z00_243,
																						BgL_arg1631z00_244);
																				}
																				if (CBOOL(BgL__andtest_1594z00_241))
																					{	/* Expand/assert.scm 35 */
																						if (INTEGERP
																							(BGl_za2bdbzd2debugza2zd2zzengine_paramz00))
																							{	/* Expand/assert.scm 36 */
																								BgL_testz00_446 =
																									(
																									(long)
																									CINT
																									(BGl_za2bdbzd2debugza2zd2zzengine_paramz00)
																									>= ((long) 1));
																							}
																						else
																							{	/* Expand/assert.scm 36 */
																								BgL_testz00_446 = ((bool_t) 0);
																							}
																					}
																				else
																					{	/* Expand/assert.scm 35 */
																						BgL_testz00_446 = ((bool_t) 0);
																					}
																			}
																	}
																	if (BgL_testz00_446)
																		{	/* Expand/assert.scm 34 */
																			return
																				BGl_replacez12z12zztools_miscz00
																				(BgL_xz00_15,
																				BGl_makezd2onezd2assertz00zzexpand_assertz00
																				(BgL_ez00_16, BgL_xz00_15,
																					BgL_varsz00_205, BgL_predz00_206));
																		}
																	else
																		{	/* Expand/assert.scm 34 */
																			return BUNSPEC;
																		}
																}
															}
														else
															{	/* Expand/assert.scm 27 */
															BgL_tagzd21391zd2_208:
																return
																	BGl_errorz00zz__errorz00(BFALSE,
																	BGl_string1720z00zzexpand_assertz00,
																	BgL_xz00_15);
															}
													}
											}
										else
											{	/* Expand/assert.scm 27 */
												obj_t BgL_carzd21432zd2_224;

												BgL_carzd21432zd2_224 = CAR(BgL_cdrzd21399zd2_211);
												if (BGl_listzf3zf3zz__r4_pairs_and_lists_6_3z00
													(BgL_carzd21432zd2_224))
													{
														obj_t BgL_predz00_472;

														obj_t BgL_varsz00_471;

														BgL_varsz00_471 = BgL_carzd21432zd2_224;
														BgL_predz00_472 = CDR(BgL_cdrzd21399zd2_211);
														BgL_predz00_206 = BgL_predz00_472;
														BgL_varsz00_205 = BgL_varsz00_471;
														goto BgL_tagzd21390zd2_207;
													}
												else
													{	/* Expand/assert.scm 27 */
														goto BgL_tagzd21391zd2_208;
													}
											}
									}
								else
									{	/* Expand/assert.scm 27 */
										obj_t BgL_carzd21445zd2_228;

										BgL_carzd21445zd2_228 = CAR(BgL_cdrzd21399zd2_211);
										if (BGl_listzf3zf3zz__r4_pairs_and_lists_6_3z00
											(BgL_carzd21445zd2_228))
											{
												obj_t BgL_predz00_478;

												obj_t BgL_varsz00_477;

												BgL_varsz00_477 = BgL_carzd21445zd2_228;
												BgL_predz00_478 = CDR(BgL_cdrzd21399zd2_211);
												BgL_predz00_206 = BgL_predz00_478;
												BgL_varsz00_205 = BgL_varsz00_477;
												goto BgL_tagzd21390zd2_207;
											}
										else
											{	/* Expand/assert.scm 27 */
												goto BgL_tagzd21391zd2_208;
											}
									}
							}
						else
							{	/* Expand/assert.scm 27 */
								goto BgL_tagzd21391zd2_208;
							}
					}
				else
					{	/* Expand/assert.scm 27 */
						goto BgL_tagzd21391zd2_208;
					}
			}
		}
	}
Beispiel #20
0
static SCM
expand_lambda_case (SCM clause, SCM alternate, SCM env)
{
  SCM formals;
  SCM rest;
  SCM req = SCM_EOL;
  SCM vars = SCM_EOL;
  SCM body;
  int nreq = 0;

  ASSERT_SYNTAX (scm_is_pair (clause) && scm_is_pair (CDR (clause)),
                 s_bad_expression, scm_cons (scm_sym_lambda, clause));

  /* Before iterating the list of formal arguments, make sure the formals
   * actually are given as either a symbol or a non-cyclic list.  */
  formals = CAR (clause);
  if (scm_is_pair (formals))
    {
      /* Dirk:FIXME:: We should check for a cyclic list of formals, and if
       * detected, report a 'Bad formals' error.  */
    }
  else
    ASSERT_SYNTAX_2 (scm_is_symbol (formals) || scm_is_null (formals),
                     s_bad_formals, formals, scm_cons (scm_sym_lambda, clause));

  /* Now iterate the list of formal arguments to check if all formals are
   * symbols, and that there are no duplicates.  */
  while (scm_is_pair (formals))
    {
      const SCM formal = CAR (formals);
      formals = CDR (formals);
      ASSERT_SYNTAX_2 (scm_is_symbol (formal), s_bad_formal, formal,
                       scm_cons (scm_sym_lambda, clause));
      ASSERT_SYNTAX_2 (!c_improper_memq (formal, formals), s_duplicate_formal,
                       formal, scm_cons (scm_sym_lambda, clause));
      nreq++;
      req = scm_cons (formal, req);
      vars = scm_cons (scm_gensym (SCM_UNDEFINED), vars);
      env = scm_acons (formal, CAR (vars), env);
    }

  ASSERT_SYNTAX_2 (scm_is_null (formals) || scm_is_symbol (formals),
                   s_bad_formal, formals, scm_cons (scm_sym_lambda, clause));
  if (scm_is_symbol (formals))
    {
      rest = formals;
      vars = scm_cons (scm_gensym (SCM_UNDEFINED), vars);
      env = scm_acons (rest, CAR (vars), env);
    }
  else
    rest = SCM_BOOL_F;
  
  body = expand_sequence (CDR (clause), env);
  req = scm_reverse_x (req, SCM_UNDEFINED);
  vars = scm_reverse_x (vars, SCM_UNDEFINED);

  if (scm_is_true (alternate) && !(SCM_EXPANDED_P (alternate) && SCM_EXPANDED_TYPE (alternate) == SCM_EXPANDED_LAMBDA_CASE))
    abort ();
    
  return LAMBDA_CASE (SCM_BOOL_F, req, SCM_BOOL_F, rest, SCM_BOOL_F,
                      SCM_EOL, vars, body, alternate);
}
Beispiel #21
0
SEXP Rprof(SEXP args)
{
    return do_Rprof(CDR(args));
}
Beispiel #22
0
static SCM
expand_lambda_star_case (SCM clause, SCM alternate, SCM env)
{
  SCM req, opt, kw, allow_other_keys, rest, formals, vars, body, tmp;
  SCM inits;
  int nreq, nopt;

  const long length = scm_ilength (clause);
  ASSERT_SYNTAX (length >= 1, s_bad_expression,
                 scm_cons (sym_lambda_star, clause));
  ASSERT_SYNTAX (length >= 2, s_missing_expression,
                 scm_cons (sym_lambda_star, clause));

  formals = CAR (clause);
  body = CDR (clause);

  nreq = nopt = 0;
  req = opt = kw = SCM_EOL;
  rest = allow_other_keys = SCM_BOOL_F;

  while (scm_is_pair (formals) && scm_is_symbol (CAR (formals)))
    {
      nreq++;
      req = scm_cons (CAR (formals), req);
      formals = scm_cdr (formals);
    }

  if (scm_is_pair (formals) && scm_is_eq (CAR (formals), kw_optional))
    {
      formals = CDR (formals);
      while (scm_is_pair (formals)
             && (scm_is_symbol (CAR (formals)) || scm_is_pair (CAR (formals))))
        {
          nopt++;
          opt = scm_cons (CAR (formals), opt);
          formals = scm_cdr (formals);
        }
    }
  
  if (scm_is_pair (formals) && scm_is_eq (CAR (formals), kw_key))
    {
      formals = CDR (formals);
      while (scm_is_pair (formals)
             && (scm_is_symbol (CAR (formals)) || scm_is_pair (CAR (formals))))
        {
          kw = scm_cons (CAR (formals), kw);
          formals = scm_cdr (formals);
        }
    }
  
  if (scm_is_pair (formals) && scm_is_eq (CAR (formals), kw_allow_other_keys))
    {
      formals = CDR (formals);
      allow_other_keys = SCM_BOOL_T;
    }
  
  if (scm_is_pair (formals) && scm_is_eq (CAR (formals), kw_rest))
    {
      ASSERT_SYNTAX (scm_ilength (formals) == 2, s_bad_formals,
                     CAR (clause));
      rest = CADR (formals);
    }
  else if (scm_is_symbol (formals))
    rest = formals;
  else
    {
      ASSERT_SYNTAX (scm_is_null (formals), s_bad_formals, CAR (clause));
      rest = SCM_BOOL_F;
    }
  
  /* Now, iterate through them a second time, building up an expansion-time
     environment, checking, expanding and canonicalizing the opt/kw init forms,
     and eventually memoizing the body as well. Note that the rest argument, if
     any, is expanded before keyword args, thus necessitating the second
     pass.

     Also note that the specific environment during expansion of init
     expressions here needs to coincide with the environment when psyntax
     expands. A lot of effort for something that is only used in the bootstrap
     expandr, you say? Yes. Yes it is.
  */

  vars = SCM_EOL;
  req = scm_reverse_x (req, SCM_EOL);
  for (tmp = req; scm_is_pair (tmp); tmp = scm_cdr (tmp))
    {
      vars = scm_cons (scm_gensym (SCM_UNDEFINED), vars);
      env = scm_acons (CAR (tmp), CAR (vars), env);
    }
  
  /* Build up opt inits and env */
  inits = SCM_EOL;
  opt = scm_reverse_x (opt, SCM_EOL);
  for (tmp = opt; scm_is_pair (tmp); tmp = scm_cdr (tmp))
    {
      SCM x = CAR (tmp);
      vars = scm_cons (scm_gensym (SCM_UNDEFINED), vars);
      env = scm_acons (x, CAR (vars), env);
      if (scm_is_symbol (x))
        inits = scm_cons (CONST (SCM_BOOL_F, SCM_BOOL_F), inits);
      else
        {
          ASSERT_SYNTAX (scm_ilength (x) == 2 && scm_is_symbol (CAR (x)),
                         s_bad_formals, CAR (clause));
          inits = scm_cons (expand (CADR (x), env), inits);
        }
      env = scm_acons (scm_is_symbol (x) ? x : CAR (x), CAR (vars), env);
    }
  if (scm_is_null (opt))
    opt = SCM_BOOL_F;
      
  /* Process rest before keyword args */
  if (scm_is_true (rest))
    {
      vars = scm_cons (scm_gensym (SCM_UNDEFINED), vars);
      env = scm_acons (rest, CAR (vars), env);
    }

  /* Build up kw inits, env, and kw-canon list */
  if (scm_is_null (kw))
    kw = SCM_BOOL_F;
  else
    {
      SCM kw_canon = SCM_EOL;
      kw = scm_reverse_x (kw, SCM_UNDEFINED);
      for (tmp = kw; scm_is_pair (tmp); tmp = scm_cdr (tmp))
        {
          SCM x, sym, k, init;
          x = CAR (tmp);
          if (scm_is_symbol (x))
            {
              sym = x;
              init = SCM_BOOL_F;
              k = scm_symbol_to_keyword (sym);
            }
          else if (scm_ilength (x) == 2 && scm_is_symbol (CAR (x)))
            {
              sym = CAR (x);
              init = CADR (x);
              k = scm_symbol_to_keyword (sym);
            }
          else if (scm_ilength (x) == 3 && scm_is_symbol (CAR (x))
                   && scm_is_keyword (CADDR (x)))
            {
              sym = CAR (x);
              init = CADR (x);
              k = CADDR (x);
            }
          else
            syntax_error (s_bad_formals, CAR (clause), SCM_UNDEFINED);

          inits = scm_cons (expand (init, env), inits);
          vars = scm_cons (scm_gensym (SCM_UNDEFINED), vars);
          kw_canon = scm_cons (scm_list_3 (k, sym, CAR (vars)), kw_canon);
          env = scm_acons (sym, CAR (vars), env);
        }
      kw_canon = scm_reverse_x (kw_canon, SCM_UNDEFINED);
      kw = scm_cons (allow_other_keys, kw_canon);
    }

  /* We should check for no duplicates, but given that psyntax does this
     already, we can punt on it here... */

  vars = scm_reverse_x (vars, SCM_UNDEFINED);
  inits = scm_reverse_x (inits, SCM_UNDEFINED);
  body = expand_sequence (body, env);

  return LAMBDA_CASE (SCM_BOOL_F, req, opt, rest, kw, inits, vars, body,
                      alternate);
}
Beispiel #23
0
SEXP unzip(SEXP args)
{
    return Runzip(CDR(args));
}
Beispiel #24
0
Datei: lisp.c Projekt: qyqx/wisp
object_t *lisp_cons (object_t * lst)
{
  DOC ("Construct a new cons cell, given car and cdr.");
  REQ (lst, 2, c_sym ("cons"));
  return c_cons (UPREF (CAR (lst)), UPREF (CAR (CDR (lst))));
}
Beispiel #25
0
Obj restArgs(Obj expr) {
	return LISTOBJ(CDR(GETLIST(expr)));
}
Beispiel #26
0
/*---------------------------------------------------------------------------
  Evaluate the S-expression pointed to by the typed-pointer p; construct the
  result value as necessary; return a typed-pointer to the result.
  ---------------------------------------------------------------------------*/
int32 eval(int32 p)
{
	int32 ty,t,v,j,f,fa,na;
	/* I think t can be static. also fa && j?  -test later. */

	int32 *endeaL;
	static double s;

#define U1 CAR(p)
#define U2 CAR(CDR(p))
#define E1 CAR(p)
#define E2 CAR(CDR(p))

#define Return(v) {traceprint(v,1); return(v);}

	traceprint(p,0);

	if(type(p)!=0)
	{/* p does ! point to a non-atomic S-expression.
	  *
	  * If p is a type-8 typed pointer to an ordinary atom whose value is a
	  * builtin || user-defined function || special form, then a typed-pointer
	  * to that atom-table entry with typecode 10, 11, 12, || 13, depending upon
	  * the value of the atom, is returned.  Note that this permits us to know
	  * the names of functions && special forms.
	  *
	  * if p is a type-8 typed pointer to an ordinary atom whose value is ! a
	  * builtin || user defined function || special form, && thus has the type-
	  * code 8, 9, 14, || 15, then a typed-pointer corresponding to the value of
	  * this atom is returned.
	  *
	  * if p is a non-type-8 typed-pointer to a number atom || to a function or
	  * special form (named || unnamed), then the same pointer p is returned.
	  */

		if ((t= type(p))!=8) Return(p); j= ptrv(p);

		/* The association list is implemented with shallow binding in the atom-
		   table, so the current values of all atoms are found in the atom table. */

		if (Atab[j].name[0] == '!')
		{tracesw= (strcmp(Atab[j].name,"!TRACE") == 0)?1:0; longjmp(env,-1);}

		if ((t= type(Atab[j].L)) == 1)
		{sprintf(sout,"%s is undefined\n",Atab[j].name); error(sout);}

		if (namedfsf_P(t)) Return(tp(t<<28,j));
		Return(Atab[j].L);
	} /* end of if (type(p)!=0) */

	/* Save the list consisting of the current function && the supplied
	   arguments as the top value of the currentin list to protect it
	   from garbage collection. The currentin list is a list of lists. */

	ciLp= newCONS(p,ciLp);

	/* compute the function || special form to be applied */
	tracesw-- ; f= eval(CAR(p)); tracesw++; ty= type(f);
	if (! fsf_P(ty)) error(" invalid function || special form");
	f= ptrv(f); if (! unnamedfsf_P(ty)) f= ptrv(Atab[f].L);

	/* now let go of the supplied input function */
	CAR(ciLp)= p= CDR(p);

	/* If f is a function (not a special form), build a new list of its
	   evaluated arguments && add it to the eaL list (the eaL list is a
	   list of lists.)  Then let go of the list of supplied arguments,
	   replacing it with the new list of evaluated arguments */
	if (f_P(ty))
	{/* compute the actual arguments */
		eaLLp= newCONS(nilptr,eaLLp);
		/* evaluate the actual arguments && build a list by tail-cons-ing! */
		endeaL= &CAR(eaLLp);
		while (p!=nilptr)
		{*endeaL= newCONS(eval(CAR(p)),nilptr); endeaL= &CDR(*endeaL); p= CDR(p);}
		/* Set p to be the first node in the evaluated arguments list. */
		p= CAR(eaLLp);

		/* Throw away the current supplied arguments list by popping the 
		   currentin list */
		ciLp= CDR(ciLp);
	}

	/* At this point p points to the first node of the actual argument
	   list.  if p == nilptr, we have a function || special form with no
	   arguments */
	if (! builtin_P(ty))
	{/* f is a non-builtin function || non-builtin special form.  do
		shallow binding of the arguments && evaluate the body of f by
		calling eval */
		fa= CAR(f); /* fa points to the first node of the formal argument list */
		na= 0;    /* na counts the number of arguments */
		/* run through the arguments && place them as the top values of
		   the formal argument atoms in the atom-table.  Push the old
		   value of each formal argument on its binding list. */
		if (type(fa) == 8 && fa != nilptr)
		{/* This will bind the entire input actual arglist as the
			single actual arg.  Sometimes, it is wrong - we should
			dereference the named fsf's in the p list, first. */

			t=ptrv(fa); 
			Atab[t].bl=newCONS(Atab[t].L,Atab[t].bl); 
			Atab[t].L=p;
			goto apply;
		}
		else
			while (p!=nilptr && dottedpair_P(type(fa)))
			{t= ptrv(CAR(fa)); fa= CDR(fa);
				Atab[t].bl= newCONS(Atab[t].L,Atab[t].bl);
				v= CAR(p); if (namedfsf_P(type(v))) v= Atab[ptrv(v)].L;
				Atab[t].L= v; ++na; p= CDR(p);
			}

		if (p!=nilptr) error("too many actuals");
		/* The following code would forbid some useful trickery. 
		   if (fa!=nilptr) error("too many formals"); */

		/* now apply the non-builtin special form || function */
apply: v= eval(CDR(f));

	   /* now unbind the actual arguments */
	   fa= CAR(f);
	   if (type(fa) == 8 && fa != nilptr)
	   {t= ptrv(fa); Atab[t].L= CAR(Atab[t].bl); Atab[t].bl= CDR(Atab[t].bl);}
	   else
		   while (na-- > 0)
		   {t= ptrv(CAR(fa)); fa= CDR(fa);
			   Atab[t].L= CAR(Atab[t].bl); Atab[t].bl= CDR(Atab[t].bl);
		   }
	} /* end non-builtins */
	else
	{/* at this point we have a builtin function || special form.  f
		is the pointer value of the atom in the atom table for the
		called function || special form && p is the pointer to the
		argument list.*/

		v= nilptr;
		switch (f) /* begin builtins */
		{case 1: /* CAR */
			if (! dottedpair_P(type(E1))) error("illegal CAR argument");
			v= CAR(E1); break;
			case 2: /* CDR */
			if (! dottedpair_P(type(E1))) error("illegal CDR argument");
			v= CDR(E1); break;
			case 3: /* CONS */
			if (s_ex_P(type(E1)) && s_ex_P(type(E2))) v= newCONS(E1,E2);
			else error("Illegal CONS arguments");
			break;

			/* for LAMBDA && SPECIAL, we could check that U1 is either an
			   ordinary atom || a list of ordinary atoms */
			case 4:/* LAMBDA */ v= tf(newCONS(U1,U2)); break;
			case 5:/* SPECIAL */ v= ts(newCONS(U1,U2)); break;
			case 6:/* SETQ */
								 f= U1; if (type(f)!=8) error("illegal assignment");
assign:  v= ptrv(f); endeaL= &Atab[v].L;
doit:    t= eval(U2);
		 switch (type(t))
		 {case 0: /* dotted pair */
			 case 8: /* ordinary atom */
			 case 9: /* number atom */
				 *endeaL= t; break;
			 case 10: /* builtin function */
			 case 11: /* builtin special form */
			 case 12: /* user-defined function */
			 case 13: /* user-defined special form */
				 *endeaL= Atab[ptrv(t)].L; break;
			 case 14: /* unnamed function */
				 *endeaL= uf(ptrv(t)); break;
			 case 15: /* unamed special form */
				 *endeaL= us(ptrv(t)); break;
		 } /* end of type(t) switch cases */

		 tracesw--; v= eval(f); tracesw++; break;

			case 7: /* ATOM */
		 if ((type(E1)) == 8 || (type(E1)) == 9) v= tptr; break;

			case 8: /* NUMBERP */
		 if (type(E1) == 9) v= tptr; break;

			case 9: /* QUOTE */ v= U1; break;
			case 10: /* LIST */ v= p; break;
			case 11: /* DO */ while (p!=nilptr) {v= CAR(p); p= CDR(p);} break;

			case 12: /* COND */
								  while (p!=nilptr)
								  {f = CAR(p);
									  if (eval(CAR(f))!=nilptr) {v=eval(CAR(CDR(f))); break;} else p=CDR(p);
								  }
								  break;

			case 13: /* PLUS */
								  v= numatom(Ntab[ptrv(E1)].num+Ntab[ptrv(E2)].num); break;

			case 14: /* TIMES */
								  v= numatom(Ntab[ptrv(E1)].num*Ntab[ptrv(E2)].num); break;

			case 15: /* DIFFERENCE */
								  v= numatom(Ntab[ptrv(E1)].num-Ntab[ptrv(E2)].num); break;

			case 16: /* QUOTIENT */
								  v= numatom(Ntab[ptrv(E1)].num/Ntab[ptrv(E2)].num); break;

			case 17: /* POWER */
								  v= numatom(pow(Ntab[ptrv(E1)].num,Ntab[ptrv(E2)].num));
								  break;

			case 18: /* FLOOR */ v= numatom(floor(Ntab[ptrv(E1)].num)); break;
			case 19: /* MINUS */ v= numatom(-Ntab[ptrv(E1)].num); break;
			case 20: /* LESSP */
								 if(Ntab[ptrv(E1)].num<Ntab[ptrv(E2)].num) v= tptr; break;

			case 21: /* GREATERP */
								 if (Ntab[ptrv(E1)].num>Ntab[ptrv(E2)].num) v= tptr; break;

			case 22: /* EVAL */ v= eval(E1); break;
			case 23: /* == */ v= (E1 == E2) ? tptr : nilptr; break;

			case 24: /* && */
							  while (p!=nilptr && eval(CAR(p))!=nilptr) p= CDR(p);
		 if (p == nilptr) v= tptr;  /* else v remains nilptr */
		 break;

			case 25: /* || */
		 while (p!=nilptr && eval(CAR(p)) == nilptr) p= CDR(p);
		 if (p!=nilptr) v= tptr;  /* else v remains nilptr */
		 break;

			case 26: /* SUM */
		 for (s= 0.0; p!=nilptr; s= s+Ntab[ptrv(CAR(p))].num, p= CDR(p));
		 v= numatom(s); break;

			case 27: /* PRODUCT */
		 for (s= 1.0; p!=nilptr; s= s*Ntab[ptrv(CAR(p))].num, p= CDR(p));
		 v= numatom(s); break;

			case 28: /* PUTPLIST */ v= E1; Atab[ptrv(v)].plist= E2; break;
			case 29: /* GETPLIST */ v= Atab[ptrv(E1)].plist; break;
			case 30: /* READ */ ourprint("\n!"); prompt= '\0'; v= read(); break;
			case 31: /* PRINT */
								if (p == nilptr) ourprint(" ");
								else while (p!=nilptr) {print(CAR(p)); ourprint(" "); p= CDR(p);}
								break;

			case 32: /* PRINTCR */
								if (p == nilptr) ourprint("\n");
								else while (p!=nilptr) {print(CAR(p)); ourprint("\n"); p= CDR(p);}
								break;

			case 33: /* MKATOM */
								strcpy(sout,Atab[ptrv(E1)].name); strcat(sout,Atab[ptrv(E2)].name);
								v= ordatom(sout); break;

			case 34: /* BODY */
								if (unnamedfsf_P(type(E1))) v= ptrv(E1);
								else if (usr_def_P(type(E1))) v= ptrv(Atab[ptrv(E1)].L);
								else error("illegal BODY argument");
								break;

			case 35: /* RPLACA */
								v= E1;
								if (! dottedpair_P(type(v))) error("illegal RPLACA argument");
								CAR(v)= E2; break;

			case 36: /* RPLACD */
								v= E1;
								if (! dottedpair_P(type(v))) error("illegal RPLACD argument");
								CDR(v)= E2; break;

			case 37: /* TSETQ */
								/* Set the top-level value of U1 to eval(U2).*/
								if (Atab[f= ptrv(U1)].bl == nilptr) goto assign;
								v= Atab[f].bl; while (CDR(v)!=nilptr) v= CDR(v);
								endeaL= &CAR(v); goto doit;

			case 38: /* NULL */
								if (E1 == nilptr) v= tptr; break;

			case 39:  /* SET */
								f= eval(U1); goto assign;

			default: error("dryrot: bad builtin case number");
		} /* end of switch cases */

	} /* end builtins */

	/* pop the eaL list || pop the currentin list, whichever is active */
	if (f_P(ty)) eaLLp= CDR(eaLLp); else ciLp= CDR(ciLp);

	Return(v);
}
Beispiel #27
0
// UGLY HACK
bool isLastExp(Obj seq) {
	List* next = CDR(GETLIST(seq));
	return next == NULL || next->car.tag == ENV;
	//return CDR(GETLIST(seq)) == NULL;
}
Beispiel #28
0
static Eterm
check_process_code(Process* rp, Module* modp)
{
    Eterm* start;
    char* mod_start;
    Uint mod_size;
    Eterm* end;
    Eterm* sp;
#ifndef HYBRID /* FIND ME! */
    ErlFunThing* funp;
    int done_gc = 0;
#endif

#define INSIDE(a) (start <= (a) && (a) < end)
    if (modp == NULL) {		/* Doesn't exist. */
	return am_false;
    } else if (modp->old_code == NULL) { /* No old code. */
	return am_false;
    }

    /*
     * Pick up limits for the module.
     */
    start = modp->old_code;
    end = (Eterm *)((char *)start + modp->old_code_length);
    mod_start = (char *) start;
    mod_size = modp->old_code_length;

    /*
     * Check if current instruction or continuation pointer points into module.
     */
    if (INSIDE(rp->i) || INSIDE(rp->cp)) {
	return am_true;
    }

    /*
     * Check all continuation pointers stored on the stack.
     */
    for (sp = rp->stop; sp < STACK_START(rp); sp++) {
	if (is_CP(*sp) && INSIDE(cp_val(*sp))) {
	    return am_true;
	}
    }

    /* 
     * Check all continuation pointers stored in stackdump
     * and clear exception stackdump if there is a pointer
     * to the module.
     */
    if (rp->ftrace != NIL) {
	struct StackTrace *s;
	ASSERT(is_list(rp->ftrace));
	s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
	if ((s->pc && INSIDE(s->pc)) ||
	    (s->current && INSIDE(s->current))) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	} else {
	    int i;
	    for (i = 0;  i < s->depth;  i++) {
		if (INSIDE(s->trace[i])) {
		    rp->freason = EXC_NULL;
		    rp->fvalue = NIL;
		    rp->ftrace = NIL;
		    break;
		}
	    }
	}
    }

    /*
     * See if there are funs that refer to the old version of the module.
     */

#ifndef HYBRID /* FIND ME! */
 rescan:
    for (funp = MSO(rp).funs; funp; funp = funp->next) {
	Eterm* fun_code;

	fun_code = funp->fe->address;

	if (INSIDE((Eterm *) funp->fe->address)) {
	    if (done_gc) {
		return am_true;
	    } else {
		/*
		 * Try to get rid of this fun by garbage collecting.
		 * Clear both fvalue and ftrace to make sure they
		 * don't hold any funs.
		 */
		rp->freason = EXC_NULL;
		rp->fvalue = NIL;
		rp->ftrace = NIL;
		done_gc = 1;
                FLAGS(rp) |= F_NEED_FULLSWEEP;
		(void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
		goto rescan;
	    }
	}
    }
#endif

    /*
     * See if there are constants inside the module referenced by the process.
     */
    done_gc = 0;
    for (;;) {
	ErlMessage* mp;

	if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, mod_start, mod_size)) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	}
	if (any_heap_ref_ptrs(rp->stop, rp->hend, mod_start, mod_size)) {
	    goto need_gc;
	}
	if (any_heap_refs(rp->heap, rp->htop, mod_start, mod_size)) {
	    goto need_gc;
	}

	if (any_heap_refs(rp->old_heap, rp->old_htop, mod_start, mod_size)) {
	    goto need_gc;
	}

	if (rp->dictionary != NULL) {
	    Eterm* start = rp->dictionary->data;
	    Eterm* end = start + rp->dictionary->used;

	    if (any_heap_ref_ptrs(start, end, mod_start, mod_size)) {
		goto need_gc;
	    }
	}

	for (mp = rp->msg.first; mp != NULL; mp = mp->next) {
	    if (any_heap_ref_ptrs(mp->m, mp->m+2, mod_start, mod_size)) {
		goto need_gc;
	    }
	}
	break;

    need_gc:
	if (done_gc) {
	    return am_true;
	} else {
	    Eterm* literals;
	    Uint lit_size;

	    /*
	     * Try to get rid of constants by by garbage collecting.
	     * Clear both fvalue and ftrace.
	     */
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	    done_gc = 1;
	    FLAGS(rp) |= F_NEED_FULLSWEEP;
	    (void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
	    literals = (Eterm *) modp->old_code[MI_LITERALS_START];
	    lit_size = (Eterm *) modp->old_code[MI_LITERALS_END] - literals;
	    erts_garbage_collect_literals(rp, literals, lit_size);
	}
    }
    return am_false;
#undef INSIDE
}
Beispiel #29
0
/* par fn gr method options */
SEXP optim(SEXP call, SEXP op, SEXP args, SEXP rho)
{
    SEXP par, fn, gr, method, options, tmp, slower, supper;
    SEXP res, value, counts, conv;
    int i, npar=0, *mask, trace, maxit, fncount = 0, grcount = 0, nREPORT, tmax;
    int ifail = 0;
    double *dpar, *opar, val = 0.0, abstol, reltol, temp;
    const char *tn;
    OptStruct OS;

    args = CDR(args);
    OS = (OptStruct) R_alloc(1, sizeof(opt_struct));
    OS->usebounds = 0;
    OS->R_env = rho;
    par = CAR(args);
    OS->names = getAttrib(par, R_NamesSymbol);
    args = CDR(args); fn = CAR(args);
    if (!isFunction(fn)) error(_("'fn' is not a function"));
    args = CDR(args); gr = CAR(args);
    args = CDR(args); method = CAR(args);
    if (!isString(method)|| LENGTH(method) != 1)
	error(_("invalid '%s' argument"), "method");
    tn = CHAR(STRING_ELT(method, 0));
    args = CDR(args); options = CAR(args);
    PROTECT(OS->R_fcall = lang2(fn, R_NilValue));
    /* I don't think duplication is needed here */
    PROTECT(par = coerceVector(duplicate(par), REALSXP));
    npar = LENGTH(par);
    dpar = vect(npar);
    opar = vect(npar);
    trace = asInteger(getListElement(options, "trace"));
    OS->fnscale = asReal(getListElement(options, "fnscale"));
    tmp = getListElement(options, "parscale");
    if (LENGTH(tmp) != npar)
	error(_("'parscale' is of the wrong length"));
    PROTECT(tmp = coerceVector(tmp, REALSXP));
    OS->parscale = vect(npar);
    for (i = 0; i < npar; i++) OS->parscale[i] = REAL(tmp)[i];
    UNPROTECT(1);
    for (i = 0; i < npar; i++)
	dpar[i] = REAL(par)[i] / (OS->parscale[i]);
    PROTECT(res = allocVector(VECSXP, 5));
    SEXP names;
    PROTECT(names = allocVector(STRSXP, 5));
    SET_STRING_ELT(names, 0, mkChar("par"));
    SET_STRING_ELT(names, 1, mkChar("value"));
    SET_STRING_ELT(names, 2, mkChar("counts"));
    SET_STRING_ELT(names, 3, mkChar("convergence"));
    SET_STRING_ELT(names, 4, mkChar("message"));
    setAttrib(res, R_NamesSymbol, names);
    UNPROTECT(1);
    PROTECT(value = allocVector(REALSXP, 1));
    PROTECT(counts = allocVector(INTSXP, 2));
    SEXP countnames;
    PROTECT(countnames = allocVector(STRSXP, 2));
    SET_STRING_ELT(countnames, 0, mkChar("function"));
    SET_STRING_ELT(countnames, 1, mkChar("gradient"));
    setAttrib(counts, R_NamesSymbol, countnames);
    UNPROTECT(1);
    PROTECT(conv = allocVector(INTSXP, 1));
    abstol = asReal(getListElement(options, "abstol"));
    reltol = asReal(getListElement(options, "reltol"));
    maxit = asInteger(getListElement(options, "maxit"));
    if (maxit == NA_INTEGER) error(_("'maxit' is not an integer"));

    if (strcmp(tn, "Nelder-Mead") == 0) {
	double alpha, beta, gamm;

	alpha = asReal(getListElement(options, "alpha"));
	beta = asReal(getListElement(options, "beta"));
	gamm = asReal(getListElement(options, "gamma"));
	nmmin(npar, dpar, opar, &val, fminfn, &ifail, abstol, reltol,
	      (void *)OS, alpha, beta, gamm, trace, &fncount, maxit);
	for (i = 0; i < npar; i++)
	    REAL(par)[i] = opar[i] * (OS->parscale[i]);
	grcount = NA_INTEGER;

    }
    else if (strcmp(tn, "SANN") == 0) {
	tmax = asInteger(getListElement(options, "tmax"));
	temp = asReal(getListElement(options, "temp"));
	if (trace) trace = asInteger(getListElement(options, "REPORT"));
	if (tmax == NA_INTEGER) error(_("'tmax' is not an integer"));
	if (!isNull(gr)) {
	    if (!isFunction(gr)) error(_("'gr' is not a function"));
		PROTECT(OS->R_gcall = lang2(gr, R_NilValue));
	} else {
	    PROTECT(OS->R_gcall = R_NilValue); /* for balance */
	}
	samin (npar, dpar, &val, fminfn, maxit, tmax, temp, trace, (void *)OS);
	for (i = 0; i < npar; i++)
	    REAL(par)[i] = dpar[i] * (OS->parscale[i]);
	fncount = npar > 0 ? maxit : 1;
	grcount = NA_INTEGER;
	UNPROTECT(1);  /* OS->R_gcall */

    } else if (strcmp(tn, "BFGS") == 0) {
	SEXP ndeps;

	nREPORT = asInteger(getListElement(options, "REPORT"));
	if (!isNull(gr)) {
	    if (!isFunction(gr)) error(_("'gr' is not a function"));
	    PROTECT(OS->R_gcall = lang2(gr, R_NilValue));
	} else {
	    PROTECT(OS->R_gcall = R_NilValue); /* for balance */
	    ndeps = getListElement(options, "ndeps");
	    if (LENGTH(ndeps) != npar)
		error(_("'ndeps' is of the wrong length"));
	    OS->ndeps = vect(npar);
	    PROTECT(ndeps = coerceVector(ndeps, REALSXP));
	    for (i = 0; i < npar; i++) OS->ndeps[i] = REAL(ndeps)[i];
	    UNPROTECT(1);
	}
	mask = (int *) R_alloc(npar, sizeof(int));
	for (i = 0; i < npar; i++) mask[i] = 1;
	vmmin(npar, dpar, &val, fminfn, fmingr, maxit, trace, mask, abstol,
	      reltol, nREPORT, (void *)OS, &fncount, &grcount, &ifail);
	for (i = 0; i < npar; i++)
	    REAL(par)[i] = dpar[i] * (OS->parscale[i]);
	UNPROTECT(1); /* OS->R_gcall */
    } else if (strcmp(tn, "CG") == 0) {
	int type;
	SEXP ndeps;

	type = asInteger(getListElement(options, "type"));
	if (!isNull(gr)) {
	    if (!isFunction(gr)) error(_("'gr' is not a function"));
	    PROTECT(OS->R_gcall = lang2(gr, R_NilValue));
	} else {
	    PROTECT(OS->R_gcall = R_NilValue); /* for balance */
	    ndeps = getListElement(options, "ndeps");
	    if (LENGTH(ndeps) != npar)
		error(_("'ndeps' is of the wrong length"));
	    OS->ndeps = vect(npar);
	    PROTECT(ndeps = coerceVector(ndeps, REALSXP));
	    for (i = 0; i < npar; i++) OS->ndeps[i] = REAL(ndeps)[i];
	    UNPROTECT(1);
	}
	cgmin(npar, dpar, opar, &val, fminfn, fmingr, &ifail, abstol,
	      reltol, (void *)OS, type, trace, &fncount, &grcount, maxit);
	for (i = 0; i < npar; i++)
	    REAL(par)[i] = opar[i] * (OS->parscale[i]);
	UNPROTECT(1); /* OS->R_gcall */

    } else if (strcmp(tn, "L-BFGS-B") == 0) {
	SEXP ndeps, smsg;
	double *lower = vect(npar), *upper = vect(npar);
	int lmm, *nbd = (int *) R_alloc(npar, sizeof(int));
	double factr, pgtol;
	char msg[60];

	nREPORT = asInteger(getListElement(options, "REPORT"));
	factr = asReal(getListElement(options, "factr"));
	pgtol = asReal(getListElement(options, "pgtol"));
	lmm = asInteger(getListElement(options, "lmm"));
	if (!isNull(gr)) {
	    if (!isFunction(gr)) error(_("'gr' is not a function"));
	    PROTECT(OS->R_gcall = lang2(gr, R_NilValue));
	} else {
	    PROTECT(OS->R_gcall = R_NilValue); /* for balance */
	    ndeps = getListElement(options, "ndeps");
	    if (LENGTH(ndeps) != npar)
		error(_("'ndeps' is of the wrong length"));
	    OS->ndeps = vect(npar);
	    PROTECT(ndeps = coerceVector(ndeps, REALSXP));
	    for (i = 0; i < npar; i++) OS->ndeps[i] = REAL(ndeps)[i];
	    UNPROTECT(1);
	}
	args = CDR(args); slower = CAR(args); /* coerce in calling code */
	args = CDR(args); supper = CAR(args);
	for (i = 0; i < npar; i++) {
	    lower[i] = REAL(slower)[i] / (OS->parscale[i]);
	    upper[i] = REAL(supper)[i] / (OS->parscale[i]);
	    if (!R_FINITE(lower[i])) {
		if (!R_FINITE(upper[i])) nbd[i] = 0; else nbd[i] = 3;
	    } else {
		if (!R_FINITE(upper[i])) nbd[i] = 1; else nbd[i] = 2;
	    }
	}
	OS->usebounds = 1;
	OS->lower = lower;
	OS->upper = upper;
	lbfgsb(npar, lmm, dpar, lower, upper, nbd, &val, fminfn, fmingr,
	       &ifail, (void *)OS, factr, pgtol, &fncount, &grcount,
	       maxit, msg, trace, nREPORT);
	for (i = 0; i < npar; i++)
	    REAL(par)[i] = dpar[i] * (OS->parscale[i]);
	UNPROTECT(1); /* OS->R_gcall */
	PROTECT(smsg = mkString(msg));
	SET_VECTOR_ELT(res, 4, smsg);
	UNPROTECT(1);
    } else
	error(_("unknown 'method'"));

    if(!isNull(OS->names)) setAttrib(par, R_NamesSymbol, OS->names);
    REAL(value)[0] = val * (OS->fnscale);
    SET_VECTOR_ELT(res, 0, par); SET_VECTOR_ELT(res, 1, value);
    INTEGER(counts)[0] = fncount; INTEGER(counts)[1] = grcount;
    SET_VECTOR_ELT(res, 2, counts);
    INTEGER(conv)[0] = ifail;
    SET_VECTOR_ELT(res, 3, conv);
    UNPROTECT(6);
    return res;
}
Beispiel #30
0
static BIF_RETTYPE append(Process* p, Eterm A, Eterm B)
{
    Eterm list;
    Eterm copy;
    Eterm last;
    Eterm* hp = NULL;
    Sint i;

    list = A;

    if (is_nil(list)) {
        BIF_RET(B);
    }

    if (is_not_list(list)) {
        BIF_ERROR(p, BADARG);
    }

    /* optimistic append on heap first */

    if ((i = HeapWordsLeft(p) / 2) < 4) {
        goto list_tail;
    }

    hp   = HEAP_TOP(p);
    copy = last = CONS(hp, CAR(list_val(list)), make_list(hp+2));
    list = CDR(list_val(list));
    hp  += 2;
    i   -= 2; /* don't use the last 2 words (extra i--;) */

    while(i-- && is_list(list)) {
        Eterm* listp = list_val(list);
        last = CONS(hp, CAR(listp), make_list(hp+2));
        list = CDR(listp);
        hp += 2;
    }

    /* A is proper and B is NIL return A as-is, don't update HTOP */

    if (is_nil(list) && is_nil(B)) {
        BIF_RET(A);
    }

    if (is_nil(list)) {
        HEAP_TOP(p) = hp;
        CDR(list_val(last)) = B;
        BIF_RET(copy);
    }

list_tail:

    if ((i = erts_list_length(list)) < 0) {
        BIF_ERROR(p, BADARG);
    }

    /* remaining list was proper and B is NIL */
    if (is_nil(B)) {
        BIF_RET(A);
    }

    if (hp) {
        /* Note: fall through case, already written
         * on the heap.
         * The last 2 words of the heap is not written yet
         */
        Eterm *hp_save = hp;
        ASSERT(i != 0);
        HEAP_TOP(p) = hp + 2;
        if (i == 1) {
            hp[0] = CAR(list_val(list));
            hp[1] = B;
            BIF_RET(copy);
        }
        hp   = HAlloc(p, 2*(i - 1));
        last = CONS(hp_save, CAR(list_val(list)), make_list(hp));
    } else {
        hp   = HAlloc(p, 2*i);
        copy = last = CONS(hp, CAR(list_val(list)), make_list(hp+2));
        hp  += 2;
    }

    list = CDR(list_val(list));
    i--;

    ASSERT(i > -1);
    while(i--) {
        Eterm* listp = list_val(list);
        last = CONS(hp, CAR(listp), make_list(hp+2));
        list = CDR(listp);
        hp  += 2;
    }

    CDR(list_val(last)) = B;
    BIF_RET(copy);
}