📄 ctalk.h
字号:
#ifndef __CTALK_H__
#define __CTALK_H__
#include "stdtp.h"
#include <setjmp.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#ifdef INSIDE_CTALK
#define DLL_ENTRY __declspec(dllexport)
#else
#define DLL_ENTRY __declspec(dllimport)
#endif
#else
#define DLL_ENTRY
#endif
enum CtkTypes {
CTK_NULL,
CTK_INTEGER,
CTK_REAL,
CTK_PRIMITIVE,
CTK_RAW_POINTER,
// object types
CTK_STRING,
CTK_ARRAY,
CTK_FILE,
CTK_MUTEX,
CTK_THREAD,
CTK_FUNCTION,
CTK_FRAME,
CTK_USER_TYPE
};
typedef long ctk_integer;
typedef unsigned long ctk_unsigned_integer;
typedef double ctk_real;
typedef struct CtkObject {
int type;
union {
ctk_integer ivalue;
ctk_real rvalue;
char* svalue;
void* ptr;
} u;
} CtkObject;
#define TO_INTEGER(o) (((o).type == CTK_INTEGER) ? (o).u.ivalue : (ctk_integer)ctkThrowException("Integer value expected"))
#define TO_REAL(o) (((o).type == CTK_REAL) ? (o).u.rvalue : (ctk_real)ctkThrowException("Real value expected"))
#define TO_STRING(o) (((o).type == CTK_STRING) ? (o).u.svalue : (char*)ctkThrowException("String value expected"))
#define CONVERT(o, type) (((o).type == (type)) ? (o).u.ptr : (void*)ctkThrowException("Conversion failed"))
#define IS_NULL(o) ((o).type == CTK_NULL)
#define IS_INTEGER(o) ((o).type == CTK_INTEGER)
#define IS_REAL(o) ((o).type == CTK_REAL)
#define IS_STRING(o) ((o).type == CTK_STRING)
#define IS_TRUE(o) ((o).u.ivalue != 0)
#define IF_STRING(o) (((o).type == CTK_STRING) ? (o).u.svalue : "")
#define IS_EQUAL(o1, o2) ctkEqual(o1, o2)
#define MAKE_INTEGER(o, i) ((o).type = CTK_INTEGER, (o).u.ivalue = (i))
#define MAKE_REAL(o, r) ((o).type = CTK_REAL, (o).u.rvalue = (r))
#define MAKE_STRING(o, s) ((o).type = CTK_STRING, (o).u.svalue = (s))
#define MAKE_RAW_POINTER(o, p) ((o).type = CTK_RAW_POINTER, (o).u.ptr = (p))
#define MAKE_MUTEX(o, m) ((o).type = CTK_MUTEX, (o).u.ptr = (m))
#define MAKE_FRAME(o, p) ((o).type = CTK_FRAME, (o).u.ptr = (p))
#define MAKE_ARRAY(o, a) ((o).type = CTK_ARRAY, (o).u.ptr = (a))
#define MAKE_FUNCTION(o, p) ((o).type = CTK_FUNCTION, (o).u.ptr = (p))
#define MAKE_NULL(o) ((o).type = CTK_NULL, (o).u.ptr = NULL)
#define MAKE_THREAD(o, t) ((o).type = CTK_THREAD, (o).u.ptr = (t))
#define MAKE_FILE(o, f) ((o).type = CTK_FILE, (o).u.ptr = (f))
#define MAKE_PRIMITIVE(o, p) ((o).type = CTK_PRIMITIVE, (o).u.ptr = (void*)(p))
#define CHECK_ALLOC(p) if (p == NULL) ctkNotEnoughMemory()
#define ALLOCATE_STRING(o, s) ((o).type = CTK_STRING, strcpy(((o).u.svalue = (char*)ctkAllocateObject(strlen(s)+1, NULL)), (s)))
DLL_ENTRY extern CtkObject ctkNull;
DLL_ENTRY extern CtkObject ctkTrue;
DLL_ENTRY extern CtkObject ctkFalse;
typedef struct CtkNode {
int line;
} CtkNode;
struct CtkStmt;
struct CtkFrame;
struct CtkModule;
struct CtkPrimitive;
typedef CtkObject (*CtkPrimitiveFunc)(int nArgs, CtkObject* args);
typedef CtkObject (*CtkPrimitiveTrampoline)(struct CtkPrimitive* prim, int nArgs, CtkObject* args);
struct CtkPrimitive;
DLL_ENTRY void ctkAddPrimitive(struct CtkPrimitive* prim);
DLL_ENTRY CtkPrimitive* ctkGetPrimitive(char const* name);
#define CHECK_PRIMITIVE_N_ARGS(nPassed, nExpected) \
if ((nPassed) != (nExpected)) ctkThrowException("Wrong number of primitive arguments")
#define CHECK_PRIMITIVE_ARGUMENT(arg, exp_type) \
if ((arg).type != (exp_type)) ctkThrowException("Incompatible type of primitive parameter")
DLL_ENTRY CtkObject ctkDefaultPrimitiveTrampolile(CtkPrimitive* prim, int nArgs, CtkObject* args);
typedef struct CtkPrimitive {
char const* name;
CtkPrimitiveFunc func;
CtkPrimitiveTrampoline trampoline;
CtkPrimitive* next;
int overload;
#ifdef __cplusplus
CtkPrimitive(char const* name, CtkPrimitiveFunc func, int overload=false,
CtkPrimitiveTrampoline trampoline=&ctkDefaultPrimitiveTrampolile) {
this->name = name;
this->func = func;
this->overload = overload;
this->trampoline = trampoline;
ctkAddPrimitive(this);
}
#endif
} CtkPrimitive;
typedef struct CtkFunction {
struct CtkStmt* stmts;
struct CtkFrame* exterior;
struct CtkFunction* next;
int nestedLevel;
int nParams;
int nLocalVars; // including parameters
char* name;
struct CtkModule* module;
} CtkFunction;
typedef struct CtkMutex {
#ifdef _WIN32
CRITICAL_SECTION cs;
#else
pthread_mutex_t mutex;
pthread_t owner;
int count;
#endif
int initialized;
} CtkMutex;
struct CtkThread;
DLL_ENTRY void ctkLockMutex(CtkMutex* mutex);
DLL_ENTRY void ctkUnlockMutex(CtkMutex* mutex);
DLL_ENTRY CtkMutex* ctkCreateMutex();
DLL_ENTRY void ctkInitializeThread(CtkThread* thread);
DLL_ENTRY void ctkDeleteMutex(CtkMutex* mutex);
#ifdef __cplusplus
class CtkCriticalSection {
public:
CtkCriticalSection(CtkMutex* mutex) {
this->mutex = mutex;
ctkLockMutex(mutex);
}
~CtkCriticalSection() {
ctkUnlockMutex(mutex);
}
private:
CtkMutex* mutex;
};
#endif
typedef struct CtkHashEntry {
struct CtkHashEntry* next;
unsigned hashCode;
CtkObject key;
CtkObject value;
} CtkHashEntry;
typedef struct CtkArray {
int nAllocated;
int nUsed;
CtkHashEntry** entries;
} CtkArray;
DLL_ENTRY CtkArray* ctkCreateArray();
DLL_ENTRY CtkArray* ctkCloneArray(CtkArray* arr);
DLL_ENTRY void ctkPutArray(CtkArray* arr, CtkObject key, CtkObject value);
DLL_ENTRY int ctkDelArray(CtkArray* arr, CtkObject key);
DLL_ENTRY void ctkAddArray(CtkArray* aDst, CtkArray* aSrc);
DLL_ENTRY void ctkSubArray(CtkArray* aDst, CtkArray* aSrc);
DLL_ENTRY CtkObject ctkGetArray(CtkArray* arr, CtkObject key);
DLL_ENTRY void ctkClearArray(CtkArray* arr);
DLL_ENTRY void ctkDeleteArray(CtkArray* arr);
DLL_ENTRY CtkArray* ctkGetCommandLineOptions();
DLL_ENTRY int ctkEqual(CtkObject o1, CtkObject o2);
DLL_ENTRY char* ctkAllocateStringLiteral(char* str);
DLL_ENTRY void ctkDeallocateStringLiteral(char* str);
typedef struct CtkQueueItem {
struct CtkQueueItem* next;
CtkObject value;
} CtkQueueItem;
typedef struct CtkQueue {
int nItems;
int nBlocked;
#ifdef _WIN32
CRITICAL_SECTION cs;
HANDLE event;
#else
pthread_mutex_t mutex;
pthread_cond_t cond;
#endif
CtkQueueItem* firstItem;
CtkQueueItem* lastItem;
} CtkQueue;
typedef void (*CtkThreadFunc)(CtkFrame* arg);
typedef void (*CtkFinalizer)(void*);
typedef struct CtkAllocHeader {
struct CtkAllocHeader* next;
CtkFinalizer finalizer;
} CtkAllocHeader;
DLL_ENTRY void* ctkAllocateObject(size_t size, CtkFinalizer finalizer);
extern int ctkMaxStackSize;
typedef struct CtkThread {
#ifdef _WIN32
DWORD threadId;
#else
pthread_t thread;
#endif
CtkThread* next;
CtkQueue queue;
CtkThreadFunc func;
CtkAllocHeader* mallocList;
CtkAllocHeader** lastHeader;
volatile int memoryAccess;
int initialized;
CtkObject* stack;
int stackSize;
volatile int sp;
void* arg;
CtkObject exceptionObject;
CtkObject usedObject; // use it to protect object from GC
void (*markFunc)(CtkThread* thread);
CtkFrame* callStack;
CtkFrame* currFrame;
CtkFrame* exceptionTrace;
jmp_buf* catchCtx;
int ctkThreadId;
} CtkThread;
#define CTK_MIN_STACK_SIZE 16*1024
DLL_ENTRY CtkThread* ctkCreateThread(CtkThreadFunc f, CtkFrame* arg, size_t stackSize);
DLL_ENTRY void ctkRunThread(CtkFrame* arg);
DLL_ENTRY void ctkDeleteThread(CtkThread* thr);
DLL_ENTRY CtkObject ctkGetMessage(CtkThread* thr);
DLL_ENTRY void ctkPutMessage(CtkThread* thr, CtkObject msg);
DLL_ENTRY int ctkGetThreadQueueLength(CtkThread* thr);
DLL_ENTRY CtkThread* ctkGetCurrentThread();
DLL_ENTRY void ctkSleep(unsigned seconds);
DLL_ENTRY long ctkGetTimeMillis();
typedef struct CtkFrame {
struct CtkFrame* up;
CtkNode* call;
CtkFunction* func;
CtkThread* thread;
int nVars;
CtkObject vars[1];
} CtkFrame;
DLL_ENTRY void ctkPrintStackTrace(CtkFrame* frame);
DLL_ENTRY char* ctkGetModuleName(CtkFrame* frame);
DLL_ENTRY char* ctkGetModuleFilePath(CtkFrame* frame);
DLL_ENTRY void ctkTrace(char const* format, ...);
typedef void (*ctkTraceFunction)(char const* format, va_list args);
DLL_ENTRY ctkTraceFunction ctkSetTraceFunction(ctkTraceFunction func);
DLL_ENTRY void* ctkThrowException(char const* msg);
DLL_ENTRY void ctkPropagateException();
typedef struct CtkFile {
char* name;
FILE* f;
} CtkFile;
DLL_ENTRY CtkFile* ctkCreateFile(char const* name, char const* fmt);
DLL_ENTRY void ctkPrint(CtkObject obj);
DLL_ENTRY void ctkPrintFile(CtkFile* file, CtkObject obj);
DLL_ENTRY void ctkFlushFile(CtkFile* file);
DLL_ENTRY void ctkDeleteFile(CtkFile* file);
DLL_ENTRY char* ctkToString(CtkObject obj, char* buf);
DLL_ENTRY void ctkAddFunction(CtkFunction* f);
DLL_ENTRY CtkFunction* ctkGetFunction(char const* name);
DLL_ENTRY CtkFrame* ctkCreateFrame(CtkFunction* func);
DLL_ENTRY CtkObject ctkCallFunction(CtkFunction* func, CtkObject* args);
DLL_ENTRY void ctkNotEnoughMemory();
DLL_ENTRY int ctkLoadLibrary(char const* name);
DLL_ENTRY void* ctkFindFunction(char const* name);
/**
* Check number and types of passed arguments
* @param nArgs number of arguments passed to the function (first parameter of any primitive)
* @param args array of arguments passed to the function (second parameter of any primitive)
* @param format format string specifying number and types of expected arguments
* In format string each character describes one correpondent parameter.
* Upercase character in format string cause checking of the argument type and copying CtkObject to the placeholder.
* Lowercase character in format string cause checking and storing arguments in native C format.
* ',' character in format string split mandatory and optional parameters.
* If type or number of parameters doesn't match, exception is thrown.
* <TABLE BORDER>
* <TR><TH>Format symbol</TH><TH>Expected C-Talk type of argument</TH><TH>Type of placeholder for parameter value</TH></TR>
* <TR><TD>o</TD><TD>any</TD><TD>CtkObject</TD></TR>
* <TR><TD>i</TD><TD>CTK_INTEGER</TD><TD>ctk_integer</TD></TR>
* <TR><TD>r</TD><TD>CTK_REAL</TD><TD>ctk_real</TD></TR>
* <TR><TD>p</TD><TD>CTK_RAW_POINTER or CTK_NULL</TD><TD>void*</TD></TR>
* <TR><TD>P</TD><TD>CTK_RAW_POINTER</TD><TD>CtkObject</TD></TR>
* <TR><TD>s</TD><TD>CTK_STRING or CTK_NULL</TD><TD>char*</TD></TR>
* <TR><TD>S</TD><TD>CTK_STRING</TD><TD>CtkObject</TD></TR>
* <TR><TD>a</TD><TD>CTK_ARRAY or CTK_NULL</TD><TD>CtkArray*</TD></TR>
* <TR><TD>A</TD><TD>CTK_ARRAY</TD><TD>CtkObject</TD></TR>
* <TR><TD>f</TD><TD>CTK_FILE or CTK_NULL</TD><TD>CtkFile*</TD></TR>
* <TR><TD>F</TD><TD>CTK_FILE</TD><TD>CtkObject</TD></TR>
* <TR><TD>m</TD><TD>CTK_MUTEX or CTK_NULL</TD><TD>CtkMutex*</TD></TR>
* <TR><TD>M</TD><TD>CTK_MUTEX</TD><TD>CtkObject</TD></TR>
* <TR><TD>t</TD><TD>CTK_THREAD or CTK_NULL</TD><TD>CtkThread*</TD></TR>
* <TR><TD>T</TD><TD>CTK_THREAD</TD><TD>CtkObject</TD></TR>
* <TR><TD>l</TD><TD>CTK_FUNCTION or CTK_NULL</TD><TD>CtkFunction*</TD></TR>
* <TR><TD>L</TD><TD>CTK_FUNCTION</TD><TD>CtkObject</TD></TR>
* <TR><TD>u</TD><TD>CTK_USER_TYPE or CTK_NULL</TD><TD>void*</TD></TR>
* <TR><TD>U</TD><TD>CTK_USER_TYPE</TD><TD>CtkObject</TD></TR>
* </TABLE>
*/
DLL_ENTRY void ctkParseArguments(int nArgs, CtkObject* args, char const* format, ...);
#ifdef USE_CTALK_EXCEPTION
class CtkException {
public:
CtkException(char const* msg) {
this->msg = msg;
}
char const* msg;
};
#endif
#ifdef __cplusplus
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -