packages feed

apple-0.3.0.0: Rc/appler.c

#include<sys/mman.h>
#include<R.h>
#include<Rinternals.h>
#include<HsFFI.h>
#include<ffi.h>
#include"../include/apple_abi.h"
#include"../c/ffi.c"

typedef size_t S;

#define Sw switch
#define C case
#define BR break;

// asReal : SEXP -> double
// asInteger : SEXP -> int
// ScalarReal : double -> SEXP
// ScalarInteger : int -> SEXP
// SEXPTYPE = INTSXP | REALSXP
// EXTPTR_PTR : SEXP -> void*

// http://adv-r.had.co.nz/C-interface.html

typedef struct AppleCache {
    U code;S code_sz;FnTy* ty;U sa;ffi_cif* ffi;
} AppleCache;

SEXP rf(U x) {
    J* i_p=x;
    J t=1;
    J rnk=i_p[0];
    SEXP dims=PROTECT(allocVector(INTSXP,(int)rnk));
    DO(i,rnk,t*=i_p[i+1];INTEGER(dims)[i]=(int)i_p[i+1]);
    SEXP ret=PROTECT(allocArray(REALSXP,dims));
    S sz=8*t;
    memcpy(REAL(ret),i_p+rnk+1,sz);
    UNPROTECT(2);
    R ret;
}

// vector only
U fr(SEXP x) {
    J rnk=1;J dim=length(x);
    J* ret=malloc(8*(2+dim));
    ret[0]=rnk;ret[1]=dim;
    memcpy(ret+2,REAL(x),dim*8);
    R ret;
}

SEXP hs_init_R(void) {
    hs_init(0,0);
    R mkString("...loaded GHC runtime");
}

SEXP ty_R(SEXP a) {
    char* err;char** err_p=&err;
    const char* inp=CHAR(asChar(a));
    char* ret=apple_printty(inp,err_p);
    if(ret==NULL) {
        SEXP ret=mkString(err);free(err);
        R ret;
    }
    R mkString(ret);
}

SEXP jit_R(SEXP a){
    char* err; char** err_p=&err;
    const char* inp=CHAR(asChar(a));
    FnTy* ty=apple_ty(inp,err_p);
    if(ty == NULL){
        SEXP ret=mkString(err);free(err);
        R ret;
    };
    U fp;S f_sz;U s;
    JC jc={(P)&malloc,(P)&free,(P)&lrand48,(P)&drand48,(P)&exp,(P)&log,(P)&pow};
    fp=apple_compile(&jc,inp,&f_sz,&s);
    AppleCache* rc=malloc(sizeof(AppleCache));
    ffi_cif* ffi=apple_ffi(ty);
    rc->code=fp;rc->code_sz=f_sz;rc->ty=ty;rc->sa=s;rc->ffi=ffi;
    // http://homepage.divms.uiowa.edu/~luke/R/simpleref.html
    // https://github.com/hadley/r-internals/blob/master/external-pointers.md
    SEXP r=R_MakeExternalPtr((U)rc,R_NilValue,R_NilValue);
    R r;
}

SEXP asm_R(SEXP a) {
    char* err; char** err_p=&err;
    const char* inp=CHAR(asChar(a));
    char* ret=apple_dumpasm(inp,err_p);
    if(ret==NULL) {
        SEXP ret=mkString(err);free(err);
        R ret;
    }
    R mkString(ret);
}

SEXP run_R(SEXP args){
    args=CDR(args);
    SEXP rc=CAR(args);
    AppleCache* c=(AppleCache*)(R_ExternalPtrAddr(rc));
    FnTy* ty=c->ty;U fp=c->code;ffi_cif* cif=c->ffi;
    SEXP r;
    int argc=ty->argc;
    U* vals=alloca(sizeof(U)*argc);
    U ret=alloca(8);
    for(int k=0;k<argc;k++){
        args=CDR(args);SEXP arg=CAR(args);
        Sw(ty->args[k]){
            C FA: {U* x=alloca(sizeof(U));x[0]=fr(arg);vals[k]=x;};BR
            C F_t: {F* xf=alloca(sizeof(F));xf[0]=asReal(arg);vals[k]=xf;};BR
            C I_t: {J* xi=alloca(sizeof(J));xi[0]=(int64_t)asInteger(arg);vals[k]=xi;};BR
        }
    }
    ffi_call(cif,fp,ret,vals);
    Sw(ty->res){
        C FA: r=rf(*(U*)ret);BR
        C F_t: r=ScalarReal(*(F*)ret);BR
        C I_t: r=ScalarInteger((int)(*(J*)ret));BR
    }
    R r;
}