2020-10-11 17:05:00 +03:00
|
|
|
#include "prim.h"
|
2021-07-17 05:59:32 +03:00
|
|
|
#include "refc_util.h"
|
2022-04-27 15:59:32 +03:00
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2020-10-11 17:05:00 +03:00
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
Value *idris2_Data_IORef_prim__newIORef(Value *erased, Value *input_value,
|
|
|
|
Value *_world) {
|
2022-04-27 15:59:32 +03:00
|
|
|
Value_IORef *ioRef = IDRIS2_NEW_VALUE(Value_IORef);
|
|
|
|
ioRef->header.tag = IOREF_TAG;
|
2024-01-22 16:25:22 +03:00
|
|
|
ioRef->v = newReference(input_value);
|
2022-04-27 15:59:32 +03:00
|
|
|
return (Value *)ioRef;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
2024-01-22 16:25:22 +03:00
|
|
|
Value *idris2_Data_IORef_prim__writeIORef(Value *erased, Value *_ioref,
|
2024-01-14 20:17:34 +03:00
|
|
|
Value *new_value, Value *_world) {
|
2024-01-22 16:25:22 +03:00
|
|
|
Value_IORef *ioref = (Value_IORef *)_ioref;
|
|
|
|
newReference(new_value);
|
|
|
|
Value *old = ioref->v;
|
|
|
|
ioref->v = new_value;
|
|
|
|
removeReference(old);
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
|
|
// System operations
|
|
|
|
// -----------------------------------
|
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
static Value *osstring = NULL;
|
|
|
|
|
|
|
|
Value *idris2_System_Info_prim__os(void) {
|
|
|
|
if (osstring == NULL) {
|
|
|
|
osstring = (Value *)makeString(
|
2020-10-11 17:05:00 +03:00
|
|
|
#ifdef _WIN32
|
2024-01-14 20:17:34 +03:00
|
|
|
"windows"
|
2020-10-11 17:05:00 +03:00
|
|
|
#elif _WIN64
|
2024-01-14 20:17:34 +03:00
|
|
|
"windows"
|
2020-10-11 17:05:00 +03:00
|
|
|
#elif __APPLE__ || __MACH__
|
2024-01-14 20:17:34 +03:00
|
|
|
"macOS"
|
2020-10-11 17:05:00 +03:00
|
|
|
#elif __linux__
|
2024-01-14 20:17:34 +03:00
|
|
|
"Linux"
|
2020-10-11 17:05:00 +03:00
|
|
|
#elif __FreeBSD__
|
2024-01-14 20:17:34 +03:00
|
|
|
"FreeBSD"
|
2020-10-21 14:20:51 +03:00
|
|
|
#elif __OpenBSD__
|
2024-01-14 20:17:34 +03:00
|
|
|
"OpenBSD"
|
2020-10-21 14:20:51 +03:00
|
|
|
#elif __NetBSD__
|
2024-01-14 20:17:34 +03:00
|
|
|
"NetBSD"
|
2020-10-21 14:20:51 +03:00
|
|
|
#elif __DragonFly__
|
2024-01-14 20:17:34 +03:00
|
|
|
"DragonFly"
|
2020-10-11 17:05:00 +03:00
|
|
|
#elif __unix || __unix__
|
2024-01-14 20:17:34 +03:00
|
|
|
"Unix"
|
2020-10-11 17:05:00 +03:00
|
|
|
#else
|
2024-01-14 20:17:34 +03:00
|
|
|
"Other"
|
2020-10-11 17:05:00 +03:00
|
|
|
#endif
|
2024-01-14 20:17:34 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return newReference(osstring);
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
2020-10-11 20:51:45 +03:00
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
// NOTE: The codegen is obviously determined at compile time,
|
|
|
|
// so the backend should optimize it by replacing it with a constant.
|
|
|
|
// It would probably also be useful for conditional compilation.
|
|
|
|
static Value *codegenstring = NULL;
|
|
|
|
|
|
|
|
Value *idris2_System_Info_prim__codegen(void) {
|
|
|
|
if (codegenstring == NULL)
|
|
|
|
codegenstring = (Value *)makeString("refc");
|
|
|
|
return newReference(codegenstring);
|
|
|
|
}
|
2022-09-08 02:44:14 +03:00
|
|
|
|
2022-04-27 15:59:32 +03:00
|
|
|
Value *idris2_crash(Value *msg) {
|
|
|
|
Value_String *str = (Value_String *)msg;
|
|
|
|
printf("ERROR: %s\n", str->str);
|
|
|
|
exit(-1);
|
2020-10-11 20:51:45 +03:00
|
|
|
}
|
|
|
|
|
2020-10-11 17:05:00 +03:00
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// // -----------------------------------
|
|
|
|
// // Array operations
|
|
|
|
// // -----------------------------------
|
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
Value *idris2_Data_IOArray_Prims_prim__newArray(Value *erased, Value *_length,
|
|
|
|
Value *v, Value *_word) {
|
2022-04-27 15:59:32 +03:00
|
|
|
int length = extractInt(_length);
|
|
|
|
Value_Array *a = makeArray(length);
|
2020-10-11 17:05:00 +03:00
|
|
|
|
2022-04-27 15:59:32 +03:00
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
a->arr[i] = newReference(v);
|
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
2022-04-27 15:59:32 +03:00
|
|
|
return (Value *)a;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
Value *idris2_Data_IOArray_Prims_prim__arraySet(Value *erased, Value *_array,
|
|
|
|
Value *_index, Value *v,
|
|
|
|
Value *_word) {
|
2022-04-27 15:59:32 +03:00
|
|
|
Value_Array *a = (Value_Array *)_array;
|
|
|
|
removeReference(a->arr[((Value_Int64 *)_index)->i64]);
|
|
|
|
a->arr[((Value_Int64 *)_index)->i64] = newReference(v);
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// -----------------------------------
|
|
|
|
// Pointer operations
|
|
|
|
// -----------------------------------
|
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
Value *idris2_Prelude_IO_prim__onCollect(Value *_erased, Value *_anyPtr,
|
|
|
|
Value *_freeingFunction,
|
|
|
|
Value *_world) {
|
2022-04-27 15:59:32 +03:00
|
|
|
Value_GCPointer *retVal = IDRIS2_NEW_VALUE(Value_GCPointer);
|
|
|
|
retVal->header.tag = GC_POINTER_TAG;
|
|
|
|
retVal->p = (Value_Pointer *)newReference(_anyPtr);
|
2024-02-12 09:43:17 +03:00
|
|
|
retVal->onCollectFct = (Value_Closure *)_freeingFunction;
|
2022-04-27 15:59:32 +03:00
|
|
|
return (Value *)retVal;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
2024-01-14 20:17:34 +03:00
|
|
|
Value *idris2_Prelude_IO_prim__onCollectAny(Value *_anyPtr,
|
|
|
|
Value *_freeingFunction,
|
|
|
|
Value *_world) {
|
2022-04-27 15:59:32 +03:00
|
|
|
Value_GCPointer *retVal = IDRIS2_NEW_VALUE(Value_GCPointer);
|
|
|
|
retVal->header.tag = GC_POINTER_TAG;
|
|
|
|
retVal->p = (Value_Pointer *)newReference(_anyPtr);
|
2024-02-12 09:43:17 +03:00
|
|
|
retVal->onCollectFct = (Value_Closure *)_freeingFunction;
|
2022-04-27 15:59:32 +03:00
|
|
|
return (Value *)retVal;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Threads
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-mutex"
|
|
|
|
// prim__makeMutex : PrimIO Mutex
|
2022-04-27 15:59:32 +03:00
|
|
|
// using pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t
|
|
|
|
// *attr)
|
|
|
|
Value *System_Concurrency_Raw_prim__makeMutex(Value *_world) {
|
|
|
|
Value_Mutex *mut = IDRIS2_NEW_VALUE(Value_Mutex);
|
|
|
|
mut->header.tag = MUTEX_TAG;
|
|
|
|
mut->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
|
|
|
|
int r = pthread_mutex_init(mut->mutex, NULL);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_mutex_init failed: %s", strerror(r));
|
|
|
|
return (Value *)mut;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-lock"
|
|
|
|
// prim__mutexAcquire : Mutex -> PrimIO ()
|
|
|
|
// using pthread_mutex_lock(pthread_mutex_t *mutex)
|
2022-04-27 15:59:32 +03:00
|
|
|
Value *System_Concurrency_Raw_prim__mutexAcquire(Value *_mutex, Value *_world) {
|
|
|
|
int r = pthread_mutex_lock(((Value_Mutex *)_mutex)->mutex);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_mutex_lock failed: %s", strerror(r));
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-unlock"
|
|
|
|
// prim__mutexRelease : Mutex -> PrimIO ()
|
2022-04-27 15:59:32 +03:00
|
|
|
// using int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
|
|
|
Value *System_Concurrency_Raw_prim__mutexRelease(Value *_mutex, Value *_world) {
|
|
|
|
int r = pthread_mutex_unlock(((Value_Mutex *)_mutex)->mutex);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_mutex_unlock failed: %s", strerror(r));
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-condition"
|
|
|
|
// prim__makeCondition : PrimIO Condition
|
2022-04-27 15:59:32 +03:00
|
|
|
// using int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t
|
|
|
|
// *attr) with standard initialisation
|
|
|
|
Value *System_Concurrency_Raw_prim__makeCondition(Value *_world) {
|
|
|
|
// typedef struct{
|
|
|
|
// Value_header header;
|
|
|
|
// pthread_cond_t *cond;
|
|
|
|
// }Value_Condition;
|
|
|
|
|
|
|
|
Value_Condition *c = IDRIS2_NEW_VALUE(Value_Condition);
|
|
|
|
c->header.tag = CONDITION_TAG;
|
|
|
|
c->cond = (pthread_cond_t *)malloc(sizeof(pthread_cond_t));
|
|
|
|
IDRIS2_REFC_VERIFY(c->cond, "malloc failed");
|
|
|
|
int r = pthread_cond_init(c->cond, NULL);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_cond_init failed: %s", strerror(r));
|
|
|
|
return (Value *)c;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-condition-wait"
|
|
|
|
// prim__conditionWait : Condition -> Mutex -> PrimIO ()
|
|
|
|
// using int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *mutex)
|
2022-04-27 15:59:32 +03:00
|
|
|
Value *System_Concurrency_Raw_prim__conditionWait(Value *_condition,
|
|
|
|
Value *_mutex,
|
|
|
|
Value *_world) {
|
|
|
|
Value_Condition *cond = (Value_Condition *)_condition;
|
|
|
|
Value_Mutex *mutex = (Value_Mutex *)_mutex;
|
|
|
|
int r = pthread_cond_wait(cond->cond, mutex->mutex);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_cond_wait failed: %s", strerror(r));
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-condition-wait-timeout"
|
|
|
|
// prim__conditionWaitTimeout : Condition -> Mutex -> Int -> PrimIO ()
|
2022-04-27 15:59:32 +03:00
|
|
|
// using int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t
|
|
|
|
// *mutex, const struct timespec *abstime)
|
|
|
|
Value *System_Concurrency_Raw_prim__conditionWaitTimeout(Value *_condition,
|
|
|
|
Value *_mutex,
|
|
|
|
Value *_timeout,
|
|
|
|
Value *_world) {
|
|
|
|
Value_Condition *cond = (Value_Condition *)_condition;
|
|
|
|
Value_Mutex *mutex = (Value_Mutex *)_mutex;
|
|
|
|
Value_Int64 *timeout = (Value_Int64 *)_timeout;
|
|
|
|
struct timespec t;
|
|
|
|
t.tv_sec = timeout->i64 / 1000000;
|
|
|
|
t.tv_nsec = timeout->i64 % 1000000;
|
|
|
|
int r = pthread_cond_timedwait(cond->cond, mutex->mutex, &t);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_cond_timedwait failed: %s", strerror(r));
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-condition-signal"
|
|
|
|
// prim__conditionSignal : Condition -> PrimIO ()
|
|
|
|
// using int pthread_cond_signal(pthread_cond_t *cond)
|
2022-04-27 15:59:32 +03:00
|
|
|
Value *System_Concurrency_Raw_prim__conditionSignal(Value *_condition,
|
|
|
|
Value *_world) {
|
|
|
|
Value_Condition *cond = (Value_Condition *)_condition;
|
|
|
|
int r = pthread_cond_signal(cond->cond);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_cond_signal failed: %s", strerror(r));
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// %foreign "scheme:blodwen-condition-broadcast"
|
|
|
|
// prim__conditionBroadcast : Condition -> PrimIO ()
|
|
|
|
// using int pthread_cond_broadcast(pthread_cond_t *cond)
|
2022-04-27 15:59:32 +03:00
|
|
|
Value *System_Concurrency_Raw_prim__conditionBroadcast(Value *_condition,
|
|
|
|
Value *_mutex) {
|
|
|
|
Value_Condition *cond = (Value_Condition *)_condition;
|
|
|
|
int r = pthread_cond_broadcast(cond->cond);
|
|
|
|
IDRIS2_REFC_VERIFY(!r, "pthread_cond_broadcast failed: %s", strerror(r));
|
|
|
|
return NULL;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
2024-02-20 17:01:06 +03:00
|
|
|
|
|
|
|
char const idris2_constr_Int[] = "Int";
|
|
|
|
char const idris2_constr_Int8[] = "Int8";
|
|
|
|
char const idris2_constr_Int16[] = "Int16";
|
|
|
|
char const idris2_constr_Int32[] = "Int32";
|
|
|
|
char const idris2_constr_Int64[] = "Int64";
|
|
|
|
char const idris2_constr_Bits8[] = "Bits8";
|
|
|
|
char const idris2_constr_Bits16[] = "Bits16";
|
|
|
|
char const idris2_constr_Bits32[] = "Bits32";
|
|
|
|
char const idris2_constr_Bits64[] = "Bits64";
|
|
|
|
char const idris2_constr_Double[] = "Double";
|
|
|
|
char const idris2_constr_Integer[] = "Integer";
|
|
|
|
char const idris2_constr_Char[] = "Char";
|
|
|
|
char const idris2_constr_String[] = "String";
|