mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-03-04 05:05:57 +08:00
docstrings support added for native functions
This commit is contained in:
parent
e6b094a926
commit
f908aa518d
@ -117,8 +117,10 @@
|
|||||||
|
|
||||||
// A macro to declare a function, with docstring, which is defined as
|
// A macro to declare a function, with docstring, which is defined as
|
||||||
// _pk_doc_<fn> = docstring; That'll used to generate function help text.
|
// _pk_doc_<fn> = docstring; That'll used to generate function help text.
|
||||||
#define DEF(fn, docstring) \
|
// [signature] is the function name and parameter names with type information.
|
||||||
static const char* DOCSTRING(fn) = docstring; \
|
// ex: `io.open(path:String, mode:String) -> io.File`
|
||||||
|
#define DEF(fn, signature, docstring) \
|
||||||
|
static const char* DOCSTRING(fn) = signature "\n\n" docstring; \
|
||||||
static void fn(PKVM* vm)
|
static void fn(PKVM* vm)
|
||||||
|
|
||||||
#endif //PK_COMMON_H
|
#endif //PK_COMMON_H
|
||||||
|
@ -2629,6 +2629,14 @@ static int compileClass(Compiler* compiler) {
|
|||||||
emitOpcode(compiler, OP_CREATE_CLASS);
|
emitOpcode(compiler, OP_CREATE_CLASS);
|
||||||
emitShort(compiler, cls_index);
|
emitShort(compiler, cls_index);
|
||||||
|
|
||||||
|
skipNewLines(compiler);
|
||||||
|
if (match(compiler, TK_STRING)) {
|
||||||
|
Token* str = &compiler->parser.previous;
|
||||||
|
int index = compilerAddConstant(compiler, str->value);
|
||||||
|
String* docstring = moduleGetStringAt(compiler->module, index);
|
||||||
|
cls->docstring = docstring->data;
|
||||||
|
}
|
||||||
|
|
||||||
skipNewLines(compiler);
|
skipNewLines(compiler);
|
||||||
while (!compiler->parser.has_syntax_error && !match(compiler, TK_END)) {
|
while (!compiler->parser.has_syntax_error && !match(compiler, TK_END)) {
|
||||||
|
|
||||||
@ -2846,6 +2854,14 @@ static void compileFunction(Compiler* compiler, FuncType fn_type) {
|
|||||||
func->arity = argc;
|
func->arity = argc;
|
||||||
compilerChangeStack(compiler, argc);
|
compilerChangeStack(compiler, argc);
|
||||||
|
|
||||||
|
skipNewLines(compiler);
|
||||||
|
if (match(compiler, TK_STRING)) {
|
||||||
|
Token* str = &compiler->parser.previous;
|
||||||
|
int index = compilerAddConstant(compiler, str->value);
|
||||||
|
String* docstring = moduleGetStringAt(compiler->module, index);
|
||||||
|
func->docstring = docstring->data;
|
||||||
|
}
|
||||||
|
|
||||||
compileBlockBody(compiler, BLOCK_FUNC);
|
compileBlockBody(compiler, BLOCK_FUNC);
|
||||||
|
|
||||||
if (fn_type == FUNC_CONSTRUCTOR) {
|
if (fn_type == FUNC_CONSTRUCTOR) {
|
||||||
|
146
src/core/core.c
146
src/core/core.c
@ -272,7 +272,7 @@ static void _collectMethods(PKVM* vm, List* list, Class* cls) {
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
DEF(coreHelp,
|
DEF(coreHelp,
|
||||||
"help([fn:Closure]) -> null\n"
|
"help([value:Closure|Class]) -> Null",
|
||||||
"It'll print the docstring the object and return.") {
|
"It'll print the docstring the object and return.") {
|
||||||
|
|
||||||
int argc = ARGC;
|
int argc = ARGC;
|
||||||
@ -290,25 +290,40 @@ DEF(coreHelp,
|
|||||||
// TODO: Extend help() to work with modules and classes.
|
// TODO: Extend help() to work with modules and classes.
|
||||||
// Add docstring (like python) to support it in pocketlang.
|
// Add docstring (like python) to support it in pocketlang.
|
||||||
|
|
||||||
Closure* closure;
|
|
||||||
if (!validateArgClosure(vm, 1, &closure)) return;
|
|
||||||
|
|
||||||
// If there ins't an io function callback, we're done.
|
|
||||||
if (vm->config.stdout_write == NULL) RET(VAR_NULL);
|
if (vm->config.stdout_write == NULL) RET(VAR_NULL);
|
||||||
|
Var value = ARG(1);
|
||||||
|
|
||||||
if (closure->fn->docstring != NULL) {
|
if (IS_OBJ_TYPE(value, OBJ_CLOSURE)) {
|
||||||
vm->config.stdout_write(vm, closure->fn->docstring);
|
Closure* closure = (Closure*) AS_OBJ(value);
|
||||||
vm->config.stdout_write(vm, "\n\n");
|
// If there ins't an io function callback, we're done.
|
||||||
|
|
||||||
|
if (closure->fn->docstring != NULL) {
|
||||||
|
vm->config.stdout_write(vm, closure->fn->docstring);
|
||||||
|
vm->config.stdout_write(vm, "\n\n");
|
||||||
|
} else {
|
||||||
|
vm->config.stdout_write(vm, "function '");
|
||||||
|
vm->config.stdout_write(vm, closure->fn->name);
|
||||||
|
vm->config.stdout_write(vm, "()' doesn't have a docstring.\n");
|
||||||
|
}
|
||||||
|
} else if (IS_OBJ_TYPE(value, OBJ_CLASS)) {
|
||||||
|
Class* cls = (Class*) AS_OBJ(value);
|
||||||
|
if (cls->docstring != NULL) {
|
||||||
|
vm->config.stdout_write(vm, cls->docstring);
|
||||||
|
vm->config.stdout_write(vm, "\n\n");
|
||||||
|
} else {
|
||||||
|
vm->config.stdout_write(vm, "class '");
|
||||||
|
vm->config.stdout_write(vm, cls->name->data);
|
||||||
|
vm->config.stdout_write(vm, "' doesn't have a docstring.\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->config.stdout_write(vm, "function '");
|
RET_ERR(newString(vm, "Expected a closure or class to get help."));
|
||||||
vm->config.stdout_write(vm, closure->fn->name);
|
|
||||||
vm->config.stdout_write(vm, "()' doesn't have a docstring.\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreDir,
|
DEF(coreDir,
|
||||||
"dir(v:var) -> List[String]\n"
|
"dir(v:Var) -> List[String]",
|
||||||
"It'll return all the elements of the variable [v]. If [v] is a module "
|
"It'll return all the elements of the variable [v]. If [v] is a module "
|
||||||
"it'll return the names of globals, functions, and classes. If it's an "
|
"it'll return the names of globals, functions, and classes. If it's an "
|
||||||
"instance it'll return all the attributes and methods.") {
|
"instance it'll return all the attributes and methods.") {
|
||||||
@ -377,7 +392,7 @@ DEF(coreDir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreAssert,
|
DEF(coreAssert,
|
||||||
"assert(condition:bool [, msg:string]) -> void\n"
|
"assert(condition:Bool [, msg:String]) -> Null",
|
||||||
"If the condition is false it'll terminate the current fiber with the "
|
"If the condition is false it'll terminate the current fiber with the "
|
||||||
"optional error message") {
|
"optional error message") {
|
||||||
|
|
||||||
@ -408,7 +423,7 @@ DEF(coreAssert,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreBin,
|
DEF(coreBin,
|
||||||
"bin(value:num) -> string\n"
|
"bin(value:Number) -> String",
|
||||||
"Returns as a binary value string with '0b' prefix.") {
|
"Returns as a binary value string with '0b' prefix.") {
|
||||||
|
|
||||||
int64_t value;
|
int64_t value;
|
||||||
@ -439,7 +454,7 @@ DEF(coreBin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreHex,
|
DEF(coreHex,
|
||||||
"hex(value:num) -> string\n"
|
"hex(value:Number) -> String",
|
||||||
"Returns as a hexadecimal value string with '0x' prefix.") {
|
"Returns as a hexadecimal value string with '0x' prefix.") {
|
||||||
|
|
||||||
int64_t value;
|
int64_t value;
|
||||||
@ -466,7 +481,7 @@ DEF(coreHex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreYield,
|
DEF(coreYield,
|
||||||
"yield([value]) -> var\n"
|
"yield([value:Var]) -> Var",
|
||||||
"Return the current function with the yield [value] to current running "
|
"Return the current function with the yield [value] to current running "
|
||||||
"fiber. If the fiber is resumed, it'll run from the next statement of the "
|
"fiber. If the fiber is resumed, it'll run from the next statement of the "
|
||||||
"yield() call. If the fiber resumed with with a value, the return value of "
|
"yield() call. If the fiber resumed with with a value, the return value of "
|
||||||
@ -481,7 +496,7 @@ DEF(coreYield,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreToString,
|
DEF(coreToString,
|
||||||
"str(value:var) -> string\n"
|
"str(valueVar) -> String",
|
||||||
"Returns the string representation of the value.") {
|
"Returns the string representation of the value.") {
|
||||||
|
|
||||||
String* str = varToString(vm, ARG(1), false);
|
String* str = varToString(vm, ARG(1), false);
|
||||||
@ -490,7 +505,7 @@ DEF(coreToString,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreChr,
|
DEF(coreChr,
|
||||||
"chr(value:num) -> string\n"
|
"chr(value:Num) -> String",
|
||||||
"Returns the ASCII string value of the integer argument.") {
|
"Returns the ASCII string value of the integer argument.") {
|
||||||
|
|
||||||
int64_t num;
|
int64_t num;
|
||||||
@ -505,7 +520,7 @@ DEF(coreChr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreOrd,
|
DEF(coreOrd,
|
||||||
"ord(value:string) -> num\n"
|
"ord(value:String) -> Number",
|
||||||
"Returns integer value of the given ASCII character.") {
|
"Returns integer value of the given ASCII character.") {
|
||||||
|
|
||||||
String* c;
|
String* c;
|
||||||
@ -519,7 +534,7 @@ DEF(coreOrd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreMin,
|
DEF(coreMin,
|
||||||
"min(a:var, b:var) -> Bool\n"
|
"min(a:Var, b:Var) -> Bool",
|
||||||
"Returns minimum of [a] and [b].") {
|
"Returns minimum of [a] and [b].") {
|
||||||
|
|
||||||
Var a = ARG(1), b = ARG(2);
|
Var a = ARG(1), b = ARG(2);
|
||||||
@ -531,7 +546,7 @@ DEF(coreMin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreMax,
|
DEF(coreMax,
|
||||||
"max(a:var, b:var) -> Bool\n"
|
"max(a:var, b:var) -> Bool",
|
||||||
"Returns maximum of [a] and [b].") {
|
"Returns maximum of [a] and [b].") {
|
||||||
|
|
||||||
Var a = ARG(1), b = ARG(2);
|
Var a = ARG(1), b = ARG(2);
|
||||||
@ -543,7 +558,7 @@ DEF(coreMax,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(corePrint,
|
DEF(corePrint,
|
||||||
"print(...) -> void\n"
|
"print(...) -> Null",
|
||||||
"Write each argument as space seperated, to the stdout and ends with a "
|
"Write each argument as space seperated, to the stdout and ends with a "
|
||||||
"newline.") {
|
"newline.") {
|
||||||
|
|
||||||
@ -562,7 +577,7 @@ DEF(corePrint,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreInput,
|
DEF(coreInput,
|
||||||
"input([msg:var]) -> string\n"
|
"input([msg:Var]) -> String",
|
||||||
"Read a line from stdin and returns it without the line ending. Accepting "
|
"Read a line from stdin and returns it without the line ending. Accepting "
|
||||||
"an optional argument [msg] and prints it before reading.") {
|
"an optional argument [msg] and prints it before reading.") {
|
||||||
|
|
||||||
@ -591,7 +606,7 @@ DEF(coreInput,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(coreExit,
|
DEF(coreExit,
|
||||||
"exit([value:num]) -> null\n"
|
"exit([value:Number]) -> Null",
|
||||||
"Exit the process with an optional exit code provided by the argument "
|
"Exit the process with an optional exit code provided by the argument "
|
||||||
"[value]. The default exit code is would be 0.") {
|
"[value]. The default exit code is would be 0.") {
|
||||||
|
|
||||||
@ -613,7 +628,7 @@ DEF(coreExit,
|
|||||||
// ---------------
|
// ---------------
|
||||||
|
|
||||||
DEF(coreListAppend,
|
DEF(coreListAppend,
|
||||||
"list_append(self:List, value:var) -> List\n"
|
"list_append(self:List, value:Var) -> List",
|
||||||
"Append the [value] to the list [self] and return the list.") {
|
"Append the [value] to the list [self] and return the list.") {
|
||||||
|
|
||||||
List* list;
|
List* list;
|
||||||
@ -627,7 +642,7 @@ DEF(coreListAppend,
|
|||||||
// TODO: currently it takes one argument (to test string interpolation).
|
// TODO: currently it takes one argument (to test string interpolation).
|
||||||
// Add join delimeter as an optional argument.
|
// Add join delimeter as an optional argument.
|
||||||
DEF(coreListJoin,
|
DEF(coreListJoin,
|
||||||
"list_join(self:List) -> String\n"
|
"list_join(self:List) -> String",
|
||||||
"Concatinate the elements of the list and return as a string.") {
|
"Concatinate the elements of the list and return as a string.") {
|
||||||
|
|
||||||
List* list;
|
List* list;
|
||||||
@ -732,7 +747,7 @@ void moduleAddFunctionInternal(PKVM* vm, Module* module,
|
|||||||
// 'lang' library methods.
|
// 'lang' library methods.
|
||||||
|
|
||||||
DEF(stdLangGC,
|
DEF(stdLangGC,
|
||||||
"lang.gc() -> num\n"
|
"lang.gc() -> Number",
|
||||||
"Trigger garbage collection and return the amount of bytes cleaned.") {
|
"Trigger garbage collection and return the amount of bytes cleaned.") {
|
||||||
|
|
||||||
size_t bytes_before = vm->bytes_allocated;
|
size_t bytes_before = vm->bytes_allocated;
|
||||||
@ -742,7 +757,7 @@ DEF(stdLangGC,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdLangDisas,
|
DEF(stdLangDisas,
|
||||||
"lang.disas(fn:Closure) -> String\n"
|
"lang.disas(fn:Closure) -> String",
|
||||||
"Returns the disassembled opcode of the function [fn].") {
|
"Returns the disassembled opcode of the function [fn].") {
|
||||||
|
|
||||||
// TODO: support dissasemble class constructors and module main body.
|
// TODO: support dissasemble class constructors and module main body.
|
||||||
@ -757,7 +772,7 @@ DEF(stdLangDisas,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdLangBackTrace,
|
DEF(stdLangBackTrace,
|
||||||
"lang.backtrace() -> String\n"
|
"lang.backtrace() -> String",
|
||||||
"Returns the backtrace as a string, each line is formated as "
|
"Returns the backtrace as a string, each line is formated as "
|
||||||
"'<function>;<file>;<line>\n'.") {
|
"'<function>;<file>;<line>\n'.") {
|
||||||
|
|
||||||
@ -806,7 +821,7 @@ DEF(stdLangBackTrace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdLangModules,
|
DEF(stdLangModules,
|
||||||
"lang.modules() -> List\n"
|
"lang.modules() -> List",
|
||||||
"Returns the list of all registered modules.") {
|
"Returns the list of all registered modules.") {
|
||||||
|
|
||||||
List* list = newList(vm, 8);
|
List* list = newList(vm, 8);
|
||||||
@ -822,7 +837,7 @@ DEF(stdLangModules,
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
DEF(stdLangDebugBreak,
|
DEF(stdLangDebugBreak,
|
||||||
"lang.debug_break() -> null\n"
|
"lang.debug_break() -> Null",
|
||||||
"A debug function for development (will be removed).") {
|
"A debug function for development (will be removed).") {
|
||||||
|
|
||||||
DEBUG_BREAK();
|
DEBUG_BREAK();
|
||||||
@ -928,19 +943,19 @@ static void _ctorFiber(PKVM* vm) {
|
|||||||
#define SELF (vm->fiber->self)
|
#define SELF (vm->fiber->self)
|
||||||
|
|
||||||
DEF(_objTypeName,
|
DEF(_objTypeName,
|
||||||
"Object.typename() -> String\n"
|
"Object.typename() -> String",
|
||||||
"Returns the type name of the object.") {
|
"Returns the type name of the object.") {
|
||||||
RET(VAR_OBJ(newString(vm, varTypeName(SELF))));
|
RET(VAR_OBJ(newString(vm, varTypeName(SELF))));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_objRepr,
|
DEF(_objRepr,
|
||||||
"Object._repr() -> String\n"
|
"Object._repr() -> String",
|
||||||
"Returns the repr string of the object.") {
|
"Returns the repr string of the object.") {
|
||||||
RET(VAR_OBJ(toRepr(vm, SELF)));
|
RET(VAR_OBJ(toRepr(vm, SELF)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_numberTimes,
|
DEF(_numberTimes,
|
||||||
"Number.times(f:fn)\n"
|
"Number.times(f:Closure)",
|
||||||
"Iterate the function [f] n times. Here n is the integral value of the "
|
"Iterate the function [f] n times. Here n is the integral value of the "
|
||||||
"number. If the number is not an integer the floor value will be taken.") {
|
"number. If the number is not an integer the floor value will be taken.") {
|
||||||
|
|
||||||
@ -960,21 +975,21 @@ DEF(_numberTimes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_numberIsint,
|
DEF(_numberIsint,
|
||||||
"Number.isint() -> bool\n"
|
"Number.isint() -> Bool",
|
||||||
"Returns true if the number is a whold number, otherwise false.") {
|
"Returns true if the number is a whold number, otherwise false.") {
|
||||||
double n = AS_NUM(SELF);
|
double n = AS_NUM(SELF);
|
||||||
RET(VAR_BOOL(floor(n) == n));
|
RET(VAR_BOOL(floor(n) == n));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_numberIsbyte,
|
DEF(_numberIsbyte,
|
||||||
"Number.isbyte() -> bool\n"
|
"Number.isbyte() -> bool",
|
||||||
"Returns true if the number is an integer and is between 0x00 and 0xff.") {
|
"Returns true if the number is an integer and is between 0x00 and 0xff.") {
|
||||||
double n = AS_NUM(SELF);
|
double n = AS_NUM(SELF);
|
||||||
RET(VAR_BOOL((floor(n) == n) && (0x00 <= n && n <= 0xff)));
|
RET(VAR_BOOL((floor(n) == n) && (0x00 <= n && n <= 0xff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stringFind,
|
DEF(_stringFind,
|
||||||
"String.find(sub:String[, start:Number=0]) -> Number\n"
|
"String.find(sub:String[, start:Number=0]) -> Number",
|
||||||
"Returns the first index of the substring [sub] found from the "
|
"Returns the first index of the substring [sub] found from the "
|
||||||
"[start] index") {
|
"[start] index") {
|
||||||
|
|
||||||
@ -1006,7 +1021,7 @@ DEF(_stringFind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stringReplace,
|
DEF(_stringReplace,
|
||||||
"String.replace(old:Sttring, new:String[, count:Number=-1]) -> String\n"
|
"String.replace(old:Sttring, new:String[, count:Number=-1]) -> String",
|
||||||
"Returns a copy of the string where [count] occurrence of the substring "
|
"Returns a copy of the string where [count] occurrence of the substring "
|
||||||
"[old] will be replaced with [new]. If [count] == -1 all the occurrence "
|
"[old] will be replaced with [new]. If [count] == -1 all the occurrence "
|
||||||
"will be replaced.") {
|
"will be replaced.") {
|
||||||
@ -1031,7 +1046,7 @@ DEF(_stringReplace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stringSplit,
|
DEF(_stringSplit,
|
||||||
"String.split(sep:String) -> List\n"
|
"String.split(sep:String) -> List",
|
||||||
"Split the string into a list of string seperated by [sep] delimeter.") {
|
"Split the string into a list of string seperated by [sep] delimeter.") {
|
||||||
|
|
||||||
String* sep;
|
String* sep;
|
||||||
@ -1045,28 +1060,28 @@ DEF(_stringSplit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stringStrip,
|
DEF(_stringStrip,
|
||||||
"String.strip() -> String\n"
|
"String.strip() -> String",
|
||||||
"Returns a copy of the string where the leading and trailing whitespace "
|
"Returns a copy of the string where the leading and trailing whitespace "
|
||||||
"removed.") {
|
"removed.") {
|
||||||
RET(VAR_OBJ(stringStrip(vm, (String*) AS_OBJ(SELF))));
|
RET(VAR_OBJ(stringStrip(vm, (String*) AS_OBJ(SELF))));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stringLower,
|
DEF(_stringLower,
|
||||||
"String.lower() -> String\n"
|
"String.lower() -> String",
|
||||||
"Returns a copy of the string where all the characters are converted to "
|
"Returns a copy of the string where all the characters are converted to "
|
||||||
"lower case letters.") {
|
"lower case letters.") {
|
||||||
RET(VAR_OBJ(stringLower(vm, (String*) AS_OBJ(SELF))));
|
RET(VAR_OBJ(stringLower(vm, (String*) AS_OBJ(SELF))));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stringUpper,
|
DEF(_stringUpper,
|
||||||
"String.lower() -> String\n"
|
"String.lower() -> String",
|
||||||
"Returns a copy of the string where all the characters are converted to "
|
"Returns a copy of the string where all the characters are converted to "
|
||||||
"upper case letters.") {
|
"upper case letters.") {
|
||||||
RET(VAR_OBJ(stringUpper(vm, (String*) AS_OBJ(SELF))));
|
RET(VAR_OBJ(stringUpper(vm, (String*) AS_OBJ(SELF))));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stingStartswith,
|
DEF(_stingStartswith,
|
||||||
"String.startswith(prefix: String | List) -> Bool\n"
|
"String.startswith(prefix: String | List) -> Bool",
|
||||||
"Returns true if the string starts the specified prefix.") {
|
"Returns true if the string starts the specified prefix.") {
|
||||||
|
|
||||||
Var prefix = ARG(1);
|
Var prefix = ARG(1);
|
||||||
@ -1097,7 +1112,7 @@ DEF(_stingStartswith,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_stingEndswith,
|
DEF(_stingEndswith,
|
||||||
"String.endswith(suffix: String | List) -> Bool\n"
|
"String.endswith(suffix: String | List) -> Bool",
|
||||||
"Returns true if the string ends with the specified suffix.") {
|
"Returns true if the string ends with the specified suffix.") {
|
||||||
|
|
||||||
Var suffix = ARG(1);
|
Var suffix = ARG(1);
|
||||||
@ -1132,7 +1147,7 @@ DEF(_stingEndswith,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_listAppend,
|
DEF(_listAppend,
|
||||||
"List.append(value:var) -> List\n"
|
"List.append(value:Var) -> List",
|
||||||
"Append the [value] to the list and return the List.") {
|
"Append the [value] to the list and return the List.") {
|
||||||
|
|
||||||
ASSERT(IS_OBJ_TYPE(SELF, OBJ_LIST), OOPS);
|
ASSERT(IS_OBJ_TYPE(SELF, OBJ_LIST), OOPS);
|
||||||
@ -1142,7 +1157,7 @@ DEF(_listAppend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_listInsert,
|
DEF(_listInsert,
|
||||||
"List.insert(index:Number, value:var) -> null\n"
|
"List.insert(index:Number, value:Var) -> Null",
|
||||||
"Insert the element at the given index. The index should be "
|
"Insert the element at the given index. The index should be "
|
||||||
"0 <= index <= list.length.") {
|
"0 <= index <= list.length.") {
|
||||||
|
|
||||||
@ -1159,7 +1174,7 @@ DEF(_listInsert,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_listPop,
|
DEF(_listPop,
|
||||||
"List.pop(index=-1) -> var\n"
|
"List.pop(index:Number=-1) -> Var",
|
||||||
"Removes the last element of the list and return it.") {
|
"Removes the last element of the list and return it.") {
|
||||||
|
|
||||||
ASSERT(IS_OBJ_TYPE(SELF, OBJ_LIST), OOPS);
|
ASSERT(IS_OBJ_TYPE(SELF, OBJ_LIST), OOPS);
|
||||||
@ -1184,7 +1199,7 @@ DEF(_listPop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_listFind,
|
DEF(_listFind,
|
||||||
"List.find(value:var) -> Number\n"
|
"List.find(value:Var) -> Number",
|
||||||
"Find the value and return its index. If the vlaue not exists "
|
"Find the value and return its index. If the vlaue not exists "
|
||||||
"it'll return -1.") {
|
"it'll return -1.") {
|
||||||
|
|
||||||
@ -1204,20 +1219,20 @@ DEF(_listFind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_listClear,
|
DEF(_listClear,
|
||||||
"List.clear() -> null\n"
|
"List.clear() -> Null",
|
||||||
"Removes all the entries in the list.") {
|
"Removes all the entries in the list.") {
|
||||||
listClear(vm, (List*) AS_OBJ(SELF));
|
listClear(vm, (List*) AS_OBJ(SELF));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_mapClear,
|
DEF(_mapClear,
|
||||||
"Map.clear() -> null\n"
|
"Map.clear() -> Null",
|
||||||
"Removes all the entries in the map.") {
|
"Removes all the entries in the map.") {
|
||||||
Map* self = (Map*) AS_OBJ(SELF);
|
Map* self = (Map*) AS_OBJ(SELF);
|
||||||
mapClear(vm, self);
|
mapClear(vm, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_mapGet,
|
DEF(_mapGet,
|
||||||
"Map.get(key:var, default=null) -> var\n"
|
"Map.get(key:Var, default=Null) -> Var",
|
||||||
"Returns the key if its in the map, otherwise the default value will "
|
"Returns the key if its in the map, otherwise the default value will "
|
||||||
"be returned.") {
|
"be returned.") {
|
||||||
|
|
||||||
@ -1233,7 +1248,7 @@ DEF(_mapGet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_mapHas,
|
DEF(_mapHas,
|
||||||
"Map.has(key:var) -> Bool\n"
|
"Map.has(key:Var) -> Bool",
|
||||||
"Returns true if the key exists.") {
|
"Returns true if the key exists.") {
|
||||||
|
|
||||||
Map* self = (Map*)AS_OBJ(SELF);
|
Map* self = (Map*)AS_OBJ(SELF);
|
||||||
@ -1242,7 +1257,7 @@ DEF(_mapHas,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_mapPop,
|
DEF(_mapPop,
|
||||||
"Map.pop(key:var) -> var\n"
|
"Map.pop(key:Var) -> Var",
|
||||||
"Pops the value at the key and return it.") {
|
"Pops the value at the key and return it.") {
|
||||||
|
|
||||||
Map* self = (Map*)AS_OBJ(SELF);
|
Map* self = (Map*)AS_OBJ(SELF);
|
||||||
@ -1254,7 +1269,7 @@ DEF(_mapPop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fiberRun,
|
DEF(_fiberRun,
|
||||||
"Fiber.run(...) -> var\n"
|
"Fiber.run(...) -> Var",
|
||||||
"Runs the fiber's function with the provided arguments and returns it's "
|
"Runs the fiber's function with the provided arguments and returns it's "
|
||||||
"return value or the yielded value if it's yielded.") {
|
"return value or the yielded value if it's yielded.") {
|
||||||
|
|
||||||
@ -1272,7 +1287,7 @@ DEF(_fiberRun,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fiberResume,
|
DEF(_fiberResume,
|
||||||
"Fiber.resume() -> var\n"
|
"Fiber.resume() -> Var",
|
||||||
"Resumes a yielded function from a previous call of fiber_run() function. "
|
"Resumes a yielded function from a previous call of fiber_run() function. "
|
||||||
"Return it's return value or the yielded value if it's yielded.") {
|
"Return it's return value or the yielded value if it's yielded.") {
|
||||||
|
|
||||||
@ -1918,6 +1933,13 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
Closure* closure = (Closure*)obj;
|
Closure* closure = (Closure*)obj;
|
||||||
switch (attrib->hash) {
|
switch (attrib->hash) {
|
||||||
|
|
||||||
|
case CHECK_HASH("_docs", 0x8fb536a9):
|
||||||
|
if (closure->fn->docstring) {
|
||||||
|
return VAR_OBJ(newString(vm, closure->fn->docstring));
|
||||||
|
} else {
|
||||||
|
return VAR_OBJ(newString(vm, ""));
|
||||||
|
}
|
||||||
|
|
||||||
case CHECK_HASH("arity", 0x3e96bd7a):
|
case CHECK_HASH("arity", 0x3e96bd7a):
|
||||||
return VAR_NUM((double)(closure->fn->arity));
|
return VAR_NUM((double)(closure->fn->arity));
|
||||||
|
|
||||||
@ -1942,9 +1964,17 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case OBJ_CLASS:
|
case OBJ_CLASS: {
|
||||||
// TODO:
|
Class* cls = (Class*) obj;
|
||||||
break;
|
if (attrib->hash == CHECK_HASH("_docs", 0x8fb536a9)) {
|
||||||
|
if (cls->docstring) {
|
||||||
|
return VAR_OBJ(newString(vm, cls->docstring));
|
||||||
|
} else {
|
||||||
|
return VAR_OBJ(newString(vm, ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
case OBJ_INST: {
|
case OBJ_INST: {
|
||||||
Instance* inst = (Instance*)obj;
|
Instance* inst = (Instance*)obj;
|
||||||
|
@ -245,19 +245,19 @@ void pkRegisterModule(PKVM* vm, PkHandle* module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name,
|
void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name,
|
||||||
pkNativeFn fptr, int arity) {
|
pkNativeFn fptr, int arity, const char* docstring) {
|
||||||
CHECK_HANDLE_TYPE(module, OBJ_MODULE);
|
CHECK_HANDLE_TYPE(module, OBJ_MODULE);
|
||||||
CHECK_ARG_NULL(fptr);
|
CHECK_ARG_NULL(fptr);
|
||||||
|
|
||||||
moduleAddFunctionInternal(vm, (Module*)AS_OBJ(module->value),
|
moduleAddFunctionInternal(vm, (Module*)AS_OBJ(module->value),
|
||||||
name, fptr, arity,
|
name, fptr, arity, docstring);
|
||||||
NULL /*TODO: Public API for function docstring.*/);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PkHandle* pkNewClass(PKVM* vm, const char* name,
|
PkHandle* pkNewClass(PKVM* vm, const char* name,
|
||||||
PkHandle* base_class, PkHandle* module,
|
PkHandle* base_class, PkHandle* module,
|
||||||
pkNewInstanceFn new_fn,
|
pkNewInstanceFn new_fn,
|
||||||
pkDeleteInstanceFn delete_fn) {
|
pkDeleteInstanceFn delete_fn,
|
||||||
|
const char* docstring) {
|
||||||
CHECK_ARG_NULL(module);
|
CHECK_ARG_NULL(module);
|
||||||
CHECK_ARG_NULL(name);
|
CHECK_ARG_NULL(name);
|
||||||
CHECK_HANDLE_TYPE(module, OBJ_MODULE);
|
CHECK_HANDLE_TYPE(module, OBJ_MODULE);
|
||||||
@ -270,7 +270,7 @@ PkHandle* pkNewClass(PKVM* vm, const char* name,
|
|||||||
|
|
||||||
Class* class_ = newClass(vm, name, (int)strlen(name),
|
Class* class_ = newClass(vm, name, (int)strlen(name),
|
||||||
super, (Module*)AS_OBJ(module->value),
|
super, (Module*)AS_OBJ(module->value),
|
||||||
NULL, NULL);
|
docstring, NULL);
|
||||||
class_->new_fn = new_fn;
|
class_->new_fn = new_fn;
|
||||||
class_->delete_fn = delete_fn;
|
class_->delete_fn = delete_fn;
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ PkHandle* pkNewClass(PKVM* vm, const char* name,
|
|||||||
|
|
||||||
void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
||||||
const char* name,
|
const char* name,
|
||||||
pkNativeFn fptr, int arity) {
|
pkNativeFn fptr, int arity, const char* docstring) {
|
||||||
CHECK_ARG_NULL(cls);
|
CHECK_ARG_NULL(cls);
|
||||||
CHECK_ARG_NULL(fptr);
|
CHECK_ARG_NULL(fptr);
|
||||||
CHECK_HANDLE_TYPE(cls, OBJ_CLASS);
|
CHECK_HANDLE_TYPE(cls, OBJ_CLASS);
|
||||||
@ -294,7 +294,7 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
|||||||
Class* class_ = (Class*)AS_OBJ(cls->value);
|
Class* class_ = (Class*)AS_OBJ(cls->value);
|
||||||
|
|
||||||
Function* fn = newFunction(vm, name, (int)strlen(name),
|
Function* fn = newFunction(vm, name, (int)strlen(name),
|
||||||
class_->owner, true, NULL, NULL);
|
class_->owner, true, docstring, NULL);
|
||||||
vmPushTempRef(vm, &fn->_super); // fn.
|
vmPushTempRef(vm, &fn->_super); // fn.
|
||||||
|
|
||||||
fn->arity = arity;
|
fn->arity = arity;
|
||||||
|
@ -504,6 +504,7 @@ Class* newClass(PKVM* vm, const char* name, int length,
|
|||||||
|
|
||||||
cls->class_of = PK_INSTANCE;
|
cls->class_of = PK_INSTANCE;
|
||||||
cls->super_class = super;
|
cls->super_class = super;
|
||||||
|
cls->docstring = docstring;
|
||||||
|
|
||||||
// Builtin types doesn't belongs to a module.
|
// Builtin types doesn't belongs to a module.
|
||||||
if (module != NULL) {
|
if (module != NULL) {
|
||||||
|
@ -55,6 +55,17 @@ extern "C" {
|
|||||||
#define PK_PUBLIC
|
#define PK_PUBLIC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Returns the docstring of the function, which is a static const char* defined
|
||||||
|
// just above the function by the DEF() macro below.
|
||||||
|
#define PK_DOCS(fn) _pk_doc_##fn
|
||||||
|
|
||||||
|
// A macro to declare a function, with docstring, which is defined as
|
||||||
|
// _pk_doc_<fn> = docstring; That'll used to generate function help text.
|
||||||
|
// [signature] is the function name and parameter names with type information.
|
||||||
|
// ex: `io.open(path:String, mode:String) -> io.File`
|
||||||
|
#define PKDEF(fn, signature, docstring) \
|
||||||
|
static const char* PK_DOCS(fn) = signature "\n\n" docstring; \
|
||||||
|
static void fn(PKVM* vm)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* POCKETLANG TYPEDEFS & CALLBACKS */
|
/* POCKETLANG TYPEDEFS & CALLBACKS */
|
||||||
@ -276,22 +287,28 @@ PK_PUBLIC void pkRegisterModule(PKVM* vm, PkHandle* module);
|
|||||||
// Add a native function to the given module. If [arity] is -1 that means
|
// Add a native function to the given module. If [arity] is -1 that means
|
||||||
// the function has variadic parameters and use pkGetArgc() to get the argc.
|
// the function has variadic parameters and use pkGetArgc() to get the argc.
|
||||||
// Note that the function will be added as a global variable of the module.
|
// Note that the function will be added as a global variable of the module.
|
||||||
|
// [docstring] is optional and could be omitted with NULL.
|
||||||
PK_PUBLIC void pkModuleAddFunction(PKVM* vm, PkHandle* module,
|
PK_PUBLIC void pkModuleAddFunction(PKVM* vm, PkHandle* module,
|
||||||
const char* name,
|
const char* name,
|
||||||
pkNativeFn fptr, int arity);
|
pkNativeFn fptr, int arity,
|
||||||
|
const char* docstring);
|
||||||
|
|
||||||
// Create a new class on the [module] with the [name] and return it.
|
// Create a new class on the [module] with the [name] and return it.
|
||||||
// If the [base_class] is NULL by default it'll set to "Object" class.
|
// If the [base_class] is NULL by default it'll set to "Object" class.
|
||||||
|
// [docstring] is optional and could be omitted with NULL.
|
||||||
PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, const char* name,
|
PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, const char* name,
|
||||||
PkHandle* base_class, PkHandle* module,
|
PkHandle* base_class, PkHandle* module,
|
||||||
pkNewInstanceFn new_fn,
|
pkNewInstanceFn new_fn,
|
||||||
pkDeleteInstanceFn delete_fn);
|
pkDeleteInstanceFn delete_fn,
|
||||||
|
const char* docstring);
|
||||||
|
|
||||||
// Add a native method to the given class. If the [arity] is -1 that means
|
// Add a native method to the given class. If the [arity] is -1 that means
|
||||||
// the method has variadic parameters and use pkGetArgc() to get the argc.
|
// the method has variadic parameters and use pkGetArgc() to get the argc.
|
||||||
|
// [docstring] is optional and could be omitted with NULL.
|
||||||
PK_PUBLIC void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
PK_PUBLIC void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
||||||
const char* name,
|
const char* name,
|
||||||
pkNativeFn fptr, int arity);
|
pkNativeFn fptr, int arity,
|
||||||
|
const char* docstring);
|
||||||
|
|
||||||
// It'll compile the pocket [source] for the module which result all the
|
// It'll compile the pocket [source] for the module which result all the
|
||||||
// functions and classes in that [source] to register on the module.
|
// functions and classes in that [source] to register on the module.
|
||||||
|
@ -42,7 +42,8 @@ void _termEventDelete(PKVM* vm, void* event) {
|
|||||||
pkRealloc(vm, event, 0);
|
pkRealloc(vm, event, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termEventGetter(PKVM* vm) {
|
PKDEF(_termEventGetter,
|
||||||
|
"term.Event@getter() -> Var", "") {
|
||||||
const char* name;
|
const char* name;
|
||||||
if (!pkValidateSlotString(vm, 1, &name, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &name, NULL)) return;
|
||||||
|
|
||||||
@ -168,41 +169,60 @@ void _registerEnums(PKVM* vm, PkHandle* term) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termInit(PKVM* vm) {
|
PKDEF(_termInit,
|
||||||
|
"term.init(capture_events:Bool) -> Null",
|
||||||
|
"Initialize terminal with raw mode for tui applications, set "
|
||||||
|
"[capture_events] true to enable event handling.") {
|
||||||
bool capture_events;
|
bool capture_events;
|
||||||
if (!pkValidateSlotBool(vm, 1, &capture_events)) return;
|
if (!pkValidateSlotBool(vm, 1, &capture_events)) return;
|
||||||
term_init(capture_events);
|
term_init(capture_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termCleanup(PKVM* vm) {
|
PKDEF(_termCleanup,
|
||||||
|
"term.cleanup() -> Null",
|
||||||
|
"Cleanup and resotre the last terminal state.") {
|
||||||
term_cleanup();
|
term_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termIsatty(PKVM* vm) {
|
PKDEF(_termIsatty,
|
||||||
|
"term.isatty() -> Bool",
|
||||||
|
"Returns true if both stdin and stdout are tty.") {
|
||||||
pkSetSlotBool(vm, 0, term_isatty());
|
pkSetSlotBool(vm, 0, term_isatty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termNewScreenBuffer(PKVM* vm) {
|
PKDEF(_termNewScreenBuffer,
|
||||||
|
"term.new_screen_buffer() -> Null",
|
||||||
|
"Switch to an alternative screen buffer.") {
|
||||||
term_new_screen_buffer();
|
term_new_screen_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termRestoreScreenBuffer(PKVM* vm) {
|
PKDEF(_termRestoreScreenBuffer,
|
||||||
|
"term.restore_screen_buffer() -> Null",
|
||||||
|
"Restore the alternative buffer which was created with "
|
||||||
|
"term.new_screen_buffer()") {
|
||||||
term_restore_screen_buffer();
|
term_restore_screen_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termGetSize(PKVM* vm) {
|
PKDEF(_termGetSize,
|
||||||
|
"term.getsize() -> types.Vector",
|
||||||
|
"Returns the screen size.") {
|
||||||
pkReserveSlots(vm, 2);
|
pkReserveSlots(vm, 2);
|
||||||
term_Vec size = term_getsize();
|
term_Vec size = term_getsize();
|
||||||
_setSlotVector(vm, 0, 1, size.x, size.y);
|
_setSlotVector(vm, 0, 1, size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termGetPosition(PKVM* vm) {
|
PKDEF(_termGetPosition,
|
||||||
|
"term.getposition() -> types.Vector",
|
||||||
|
"Returns the cursor position in the screen on a zero based coordinate.") {
|
||||||
pkReserveSlots(vm, 2);
|
pkReserveSlots(vm, 2);
|
||||||
term_Vec pos = term_getposition();
|
term_Vec pos = term_getposition();
|
||||||
_setSlotVector(vm, 0, 1, pos.x, pos.y);
|
_setSlotVector(vm, 0, 1, pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termSetPosition(PKVM* vm) {
|
PKDEF(_termSetPosition,
|
||||||
|
"term.setposition(pos:types.Vector | {x, y}) -> Null",
|
||||||
|
"Set cursor position at the [position] in the screen no a zero"
|
||||||
|
"based coordinate.") {
|
||||||
double x, y;
|
double x, y;
|
||||||
|
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
@ -224,7 +244,10 @@ void _termSetPosition(PKVM* vm) {
|
|||||||
term_setposition(pos);
|
term_setposition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _termReadEvent(PKVM* vm) {
|
PKDEF(_termReadEvent,
|
||||||
|
"term.read_event(event:term.Event) -> Bool",
|
||||||
|
"Read an event and update the argument [event] and return true."
|
||||||
|
"If no event was read it'll return false.") {
|
||||||
pkReserveSlots(vm, 3);
|
pkReserveSlots(vm, 3);
|
||||||
pkSetSlotHandle(vm, 2, _cls_term_event);
|
pkSetSlotHandle(vm, 2, _cls_term_event);
|
||||||
if (!pkValidateSlotInstanceOf(vm, 1, 2)) return;
|
if (!pkValidateSlotInstanceOf(vm, 1, 2)) return;
|
||||||
@ -233,9 +256,10 @@ void _termReadEvent(PKVM* vm) {
|
|||||||
pkSetSlotBool(vm, 0, term_read_event(event));
|
pkSetSlotBool(vm, 0, term_read_event(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
// On windows it'll set stdout to binary mode, on other platforms this function
|
PKDEF(_termBinaryMode,
|
||||||
// won't make make any difference.
|
"term.binary_mode() -> Null",
|
||||||
void _termBinaryMode(PKVM* vm) {
|
"On windows it'll set stdout to binary mode, on other platforms this "
|
||||||
|
"function won't make make any difference.") {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
(void) _setmode(_fileno(stdout), _O_BINARY);
|
(void) _setmode(_fileno(stdout), _O_BINARY);
|
||||||
#endif
|
#endif
|
||||||
@ -249,25 +273,29 @@ void registerModuleTerm(PKVM* vm) {
|
|||||||
PkHandle* term = pkNewModule(vm, "term");
|
PkHandle* term = pkNewModule(vm, "term");
|
||||||
|
|
||||||
_registerEnums(vm, term);
|
_registerEnums(vm, term);
|
||||||
pkModuleAddFunction(vm, term, "init", _termInit, 1);
|
REGISTER_FN(term, "init", _termInit, 1);
|
||||||
pkModuleAddFunction(vm, term, "cleanup", _termCleanup, 0);
|
REGISTER_FN(term, "cleanup", _termCleanup, 0);
|
||||||
pkModuleAddFunction(vm, term, "isatty", _termIsatty, 0);
|
REGISTER_FN(term, "isatty", _termIsatty, 0);
|
||||||
pkModuleAddFunction(vm, term, "new_screen_buffer", _termNewScreenBuffer, 0);
|
REGISTER_FN(term, "new_screen_buffer", _termNewScreenBuffer, 0);
|
||||||
pkModuleAddFunction(vm, term, "restore_screen_buffer", _termRestoreScreenBuffer, 0);
|
REGISTER_FN(term, "restore_screen_buffer", _termRestoreScreenBuffer, 0);
|
||||||
pkModuleAddFunction(vm, term, "getsize", _termGetSize, 0);
|
REGISTER_FN(term, "getsize", _termGetSize, 0);
|
||||||
pkModuleAddFunction(vm, term, "getposition", _termGetPosition, 0);
|
REGISTER_FN(term, "getposition", _termGetPosition, 0);
|
||||||
pkModuleAddFunction(vm, term, "setposition", _termSetPosition, -1);
|
REGISTER_FN(term, "setposition", _termSetPosition, -1);
|
||||||
pkModuleAddFunction(vm, term, "read_event", _termReadEvent, 1);
|
REGISTER_FN(term, "read_event", _termReadEvent, 1);
|
||||||
|
|
||||||
_cls_term_event = pkNewClass(vm, "Event", NULL, term, _termEventNew, _termEventDelete);
|
_cls_term_event = pkNewClass(vm, "Event", NULL, term,
|
||||||
pkClassAddMethod(vm, _cls_term_event, "@getter", _termEventGetter, 1);
|
_termEventNew, _termEventDelete,
|
||||||
|
"The terminal event type, that'll be used at term.read_event function to "
|
||||||
|
"fetch events.");
|
||||||
|
|
||||||
|
ADD_METHOD(_cls_term_event, "@getter", _termEventGetter, 1);
|
||||||
|
|
||||||
pkModuleAddSource(vm, term, ext_term_pk);
|
pkModuleAddSource(vm, term, ext_term_pk);
|
||||||
|
|
||||||
// This is required for language server. Since we need to send '\r\n' to
|
// This is required for language server. Since we need to send '\r\n' to
|
||||||
// the lsp client but windows will change '\n' to '\r\n' and it'll become
|
// the lsp client but windows will change '\n' to '\r\n' and it'll become
|
||||||
// '\r\r\n', binary mode will prevent this.
|
// '\r\r\n', binary mode will prevent this.
|
||||||
pkModuleAddFunction(vm, term, "binary_mode", _termBinaryMode, 0);
|
REGISTER_FN(term, "binary_mode", _termBinaryMode, 0);
|
||||||
|
|
||||||
pkRegisterModule(vm, term);
|
pkRegisterModule(vm, term);
|
||||||
pkReleaseHandle(vm, term);
|
pkReleaseHandle(vm, term);
|
||||||
|
@ -22,9 +22,9 @@ typedef void* (*pkRealloc_t)(PKVM*, void*, size_t);
|
|||||||
typedef void (*pkReleaseHandle_t)(PKVM*, PkHandle*);
|
typedef void (*pkReleaseHandle_t)(PKVM*, PkHandle*);
|
||||||
typedef PkHandle* (*pkNewModule_t)(PKVM*, const char*);
|
typedef PkHandle* (*pkNewModule_t)(PKVM*, const char*);
|
||||||
typedef void (*pkRegisterModule_t)(PKVM*, PkHandle*);
|
typedef void (*pkRegisterModule_t)(PKVM*, PkHandle*);
|
||||||
typedef void (*pkModuleAddFunction_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int);
|
typedef void (*pkModuleAddFunction_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int, const char*);
|
||||||
typedef PkHandle* (*pkNewClass_t)(PKVM*, const char*, PkHandle*, PkHandle*, pkNewInstanceFn, pkDeleteInstanceFn);
|
typedef PkHandle* (*pkNewClass_t)(PKVM*, const char*, PkHandle*, PkHandle*, pkNewInstanceFn, pkDeleteInstanceFn, const char*);
|
||||||
typedef void (*pkClassAddMethod_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int);
|
typedef void (*pkClassAddMethod_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int, const char*);
|
||||||
typedef void (*pkModuleAddSource_t)(PKVM*, PkHandle*, const char*);
|
typedef void (*pkModuleAddSource_t)(PKVM*, PkHandle*, const char*);
|
||||||
typedef PkResult (*pkRunString_t)(PKVM*, const char*);
|
typedef PkResult (*pkRunString_t)(PKVM*, const char*);
|
||||||
typedef PkResult (*pkRunFile_t)(PKVM*, const char*);
|
typedef PkResult (*pkRunFile_t)(PKVM*, const char*);
|
||||||
@ -131,9 +131,10 @@ typedef struct {
|
|||||||
pkImportModule_t pkImportModule_ptr;
|
pkImportModule_t pkImportModule_ptr;
|
||||||
} PkNativeApi;
|
} PkNativeApi;
|
||||||
|
|
||||||
#define PK_API_INIT_FN_NAME "pkInitApi"
|
#define PK_API_INIT_FN_NAME "pkInitApi"
|
||||||
#define PK_EXPORT_FN_NAME "pkExportModule"
|
#define PK_EXPORT_FN_NAME "pkExportModule"
|
||||||
#define PK_CLEANUP_FN_NAME "pkCleanupModule"
|
|
||||||
|
#define PK_CLEANUP_FN_NAME "pkCleanupModule"
|
||||||
|
|
||||||
typedef void (*pkInitApiFn)(PkNativeApi*);
|
typedef void (*pkInitApiFn)(PkNativeApi*);
|
||||||
typedef PkHandle* (*pkExportModuleFn)(PKVM*);
|
typedef PkHandle* (*pkExportModuleFn)(PKVM*);
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
#define REPORT_ERRNO(fn) \
|
#define REPORT_ERRNO(fn) \
|
||||||
pkSetRuntimeErrorFmt(vm, "C." #fn " errno:%i - %s.", errno, strerror(errno))
|
pkSetRuntimeErrorFmt(vm, "C." #fn " errno:%i - %s.", errno, strerror(errno))
|
||||||
|
|
||||||
|
#define REGISTER_FN(module, name, fn, argc) \
|
||||||
|
pkModuleAddFunction(vm, module, name, fn, argc, PK_DOCS(fn))
|
||||||
|
|
||||||
|
#define ADD_METHOD(cls, name, fn, argc) \
|
||||||
|
pkClassAddMethod(vm, cls, name, fn, argc, PK_DOCS(fn));
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* SHARED FUNCTIONS */
|
/* SHARED FUNCTIONS */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -25,7 +25,9 @@ void _deleteDummy(PKVM* vm, void* ptr) {
|
|||||||
pkRealloc(vm, ptr, 0);
|
pkRealloc(vm, ptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyInit, "") {
|
DEF(_dummyInit,
|
||||||
|
"dummy.Dummy._init(n:Number)",
|
||||||
|
"Initialize a dummy instance with [n].") {
|
||||||
double val;
|
double val;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &val)) return;
|
if (!pkValidateSlotNumber(vm, 1, &val)) return;
|
||||||
|
|
||||||
@ -33,7 +35,8 @@ DEF(_dummyInit, "") {
|
|||||||
self->val = val;
|
self->val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyGetter, "") {
|
DEF(_dummyGetter, "dummy.Dummy.@getter()", "") {
|
||||||
|
|
||||||
const char* name = pkGetSlotString(vm, 1, NULL);
|
const char* name = pkGetSlotString(vm, 1, NULL);
|
||||||
Dummy* self = (Dummy*)pkGetSelf(vm);
|
Dummy* self = (Dummy*)pkGetSelf(vm);
|
||||||
if (strcmp("val", name) == 0) {
|
if (strcmp("val", name) == 0) {
|
||||||
@ -42,7 +45,7 @@ DEF(_dummyGetter, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummySetter, "") {
|
DEF(_dummySetter, "dummy.Dummy.@setter()", "") {
|
||||||
const char* name = pkGetSlotString(vm, 1, NULL);
|
const char* name = pkGetSlotString(vm, 1, NULL);
|
||||||
Dummy* self = (Dummy*)pkGetSelf(vm);
|
Dummy* self = (Dummy*)pkGetSelf(vm);
|
||||||
if (strcmp("val", name) == 0) {
|
if (strcmp("val", name) == 0) {
|
||||||
@ -53,7 +56,9 @@ DEF(_dummySetter, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyAdd, "") {
|
DEF(_dummyAdd,
|
||||||
|
"dummy.Dummy.+(other:dummy.Dummy) -> dummy.Dummy",
|
||||||
|
"Adds two dummy instances.") {
|
||||||
Dummy* self = (Dummy*) pkGetSelf(vm);
|
Dummy* self = (Dummy*) pkGetSelf(vm);
|
||||||
|
|
||||||
pkReserveSlots(vm, 4); // Now we have slots [0, 1, 2, 3].
|
pkReserveSlots(vm, 4); // Now we have slots [0, 1, 2, 3].
|
||||||
@ -72,7 +77,9 @@ DEF(_dummyAdd, "") {
|
|||||||
if (!pkNewInstance(vm, 2, 0, 1, 3)) return;
|
if (!pkNewInstance(vm, 2, 0, 1, 3)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyEq, "") {
|
DEF(_dummyEq,
|
||||||
|
"dummy.Dummy.==(other:dummy.Dummy) -> Bool",
|
||||||
|
"Check if two dummy instances are the equal.") {
|
||||||
|
|
||||||
// TODO: Currently there is no way of getting another native instance
|
// TODO: Currently there is no way of getting another native instance
|
||||||
// So, it's impossible to check self == other. So for now checking with
|
// So, it's impossible to check self == other. So for now checking with
|
||||||
@ -84,7 +91,9 @@ DEF(_dummyEq, "") {
|
|||||||
pkSetSlotBool(vm, 0, value == self->val);
|
pkSetSlotBool(vm, 0, value == self->val);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyGt, "") {
|
DEF(_dummyGt,
|
||||||
|
"dummy.Dummy.>(other:dummy.Dummy) -> Bool",
|
||||||
|
"Check if the dummy instance is greater than [other].") {
|
||||||
|
|
||||||
// TODO: Currently there is no way of getting another native instance
|
// TODO: Currently there is no way of getting another native instance
|
||||||
// So, it's impossible to check self == other. So for now checking with
|
// So, it's impossible to check self == other. So for now checking with
|
||||||
@ -97,7 +106,7 @@ DEF(_dummyGt, "") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyMethod,
|
DEF(_dummyMethod,
|
||||||
"Dummy.a_method(n1:num, n2:num) -> num\n"
|
"Dummy.a_method(n1:Number, n2:Number) -> Number",
|
||||||
"A dummy method to check dummy method calls. Will take 2 number arguments "
|
"A dummy method to check dummy method calls. Will take 2 number arguments "
|
||||||
"and return the multiplication.") {
|
"and return the multiplication.") {
|
||||||
|
|
||||||
@ -109,7 +118,7 @@ DEF(_dummyMethod,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyFunction,
|
DEF(_dummyFunction,
|
||||||
"dummy.afunc(s1:str, s2:str) -> str\n"
|
"dummy.afunc(s1:String, s2:String) -> String",
|
||||||
"A dummy function the'll return s2 + s1.") {
|
"A dummy function the'll return s2 + s1.") {
|
||||||
|
|
||||||
const char *s1, *s2;
|
const char *s1, *s2;
|
||||||
@ -120,8 +129,8 @@ DEF(_dummyFunction,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyCallNative,
|
DEF(_dummyCallNative,
|
||||||
"dummy.call_native(f:fn) -> void\n"
|
"dummy.call_native(fn:Closure) -> Null",
|
||||||
"Calls the function 'f' with arguments 'foo', 42, false.") {
|
"Calls the function 'fn' with arguments 'foo', 42, false.") {
|
||||||
if (!pkValidateSlotType(vm, 1, PK_CLOSURE)) return;
|
if (!pkValidateSlotType(vm, 1, PK_CLOSURE)) return;
|
||||||
|
|
||||||
pkReserveSlots(vm, 5); // Now we have slots [0, 1, 2, 3, 4].
|
pkReserveSlots(vm, 5); // Now we have slots [0, 1, 2, 3, 4].
|
||||||
@ -134,7 +143,7 @@ DEF(_dummyCallNative,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_dummyCallMethod,
|
DEF(_dummyCallMethod,
|
||||||
"dummy.call_method(o:Obj, method:str, a1, a2) -> \n"
|
"dummy.call_method(o:Var, method:String, a1:Var, a2:Var) -> Var",
|
||||||
"Calls the method int the object [o] with two arguments [a1] and [a2].") {
|
"Calls the method int the object [o] with two arguments [a1] and [a2].") {
|
||||||
const char* method;
|
const char* method;
|
||||||
if (!pkValidateSlotString(vm, 2, &method, NULL)) return;
|
if (!pkValidateSlotString(vm, 2, &method, NULL)) return;
|
||||||
@ -152,19 +161,20 @@ void registerModuleDummy(PKVM* vm) {
|
|||||||
|
|
||||||
PkHandle* dummy = pkNewModule(vm, "dummy");
|
PkHandle* dummy = pkNewModule(vm, "dummy");
|
||||||
|
|
||||||
pkModuleAddFunction(vm, dummy, "afunc", _dummyFunction, 2);
|
REGISTER_FN(dummy, "afunc", _dummyFunction, 2);
|
||||||
pkModuleAddFunction(vm, dummy, "call_native", _dummyCallNative, 1);
|
REGISTER_FN(dummy, "call_native", _dummyCallNative, 1);
|
||||||
pkModuleAddFunction(vm, dummy, "call_method", _dummyCallMethod, 4);
|
REGISTER_FN(dummy, "call_method", _dummyCallMethod, 4);
|
||||||
|
|
||||||
PkHandle* cls_dummy = pkNewClass(vm, "Dummy", NULL, dummy,
|
PkHandle* cls_dummy = pkNewClass(vm, "Dummy", NULL, dummy,
|
||||||
_newDummy, _deleteDummy);
|
_newDummy, _deleteDummy, NULL);
|
||||||
pkClassAddMethod(vm, cls_dummy, "_init", _dummyInit, 1);
|
ADD_METHOD(cls_dummy, "_init", _dummyInit, 1);
|
||||||
pkClassAddMethod(vm, cls_dummy, "@getter", _dummyGetter, 1);
|
ADD_METHOD(cls_dummy, "@getter", _dummyGetter, 1);
|
||||||
pkClassAddMethod(vm, cls_dummy, "@setter", _dummySetter, 2);
|
ADD_METHOD(cls_dummy, "@setter", _dummySetter, 2);
|
||||||
pkClassAddMethod(vm, cls_dummy, "+", _dummyAdd, 1);
|
ADD_METHOD(cls_dummy, "+", _dummyAdd, 1);
|
||||||
pkClassAddMethod(vm, cls_dummy, "==", _dummyEq, 1);
|
ADD_METHOD(cls_dummy, "==", _dummyEq, 1);
|
||||||
pkClassAddMethod(vm, cls_dummy, ">", _dummyGt, 1);
|
ADD_METHOD(cls_dummy, ">", _dummyGt, 1);
|
||||||
pkClassAddMethod(vm, cls_dummy, "a_method", _dummyMethod, 2);
|
ADD_METHOD(cls_dummy, "a_method", _dummyMethod, 2);
|
||||||
|
|
||||||
pkReleaseHandle(vm, cls_dummy);
|
pkReleaseHandle(vm, cls_dummy);
|
||||||
|
|
||||||
pkRegisterModule(vm, dummy);
|
pkRegisterModule(vm, dummy);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF(_ioWrite,
|
DEF(_ioWrite,
|
||||||
"io.write(stream:var, bytes:String) -> null\n"
|
"io.write(stream:Var, bytes:String) -> Null",
|
||||||
"Warning: the function is subjected to be changed anytime soon.\n"
|
"Warning: the function is subjected to be changed anytime soon.\n"
|
||||||
"Write [bytes] string to the stream. stream should be any of io.stdin, "
|
"Write [bytes] string to the stream. stream should be any of io.stdin, "
|
||||||
"io.stdout, io.stderr.") {
|
"io.stdout, io.stderr.") {
|
||||||
@ -46,14 +46,14 @@ DEF(_ioWrite,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_ioFlush,
|
DEF(_ioFlush,
|
||||||
"io.flush() -> null\n"
|
"io.flush() -> Null",
|
||||||
"Warning: the function is subjected to be changed anytime soon.\n"
|
"Warning: the function is subjected to be changed anytime soon.\n"
|
||||||
"Flush stdout buffer.\n") {
|
"Flush stdout buffer.") {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_ioGetc,
|
DEF(_ioGetc,
|
||||||
"io.getc() -> String\n"
|
"io.getc() -> String",
|
||||||
"Read a single character from stdin and return it.") {
|
"Read a single character from stdin and return it.") {
|
||||||
char c = (char) fgetc(stdin);
|
char c = (char) fgetc(stdin);
|
||||||
pkSetSlotStringLength(vm, 0, &c, 1);
|
pkSetSlotStringLength(vm, 0, &c, 1);
|
||||||
@ -129,7 +129,21 @@ void _fileDelete(PKVM* vm, void* ptr) {
|
|||||||
/* FILE MODULE FUNCTIONS */
|
/* FILE MODULE FUNCTIONS */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
DEF(_fileOpen, "") {
|
DEF(_fileOpen,
|
||||||
|
"io.File.open(path:String, mode:String) -> Null",
|
||||||
|
"Opens a file at the [path] with the [mode]. Path should be either "
|
||||||
|
"absolute or relative to the current working directory. and [mode] can be"
|
||||||
|
"'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).\n"
|
||||||
|
"\n"
|
||||||
|
" mode | If already exists | If does not exist |\n"
|
||||||
|
" -----+-------------------+-------------------|\n"
|
||||||
|
" 'r' | read from start | failure to open |\n"
|
||||||
|
" 'w' | destroy contents | create new |\n"
|
||||||
|
" 'a' | write to end | create new |\n"
|
||||||
|
" 'r+' | read from start | error |\n"
|
||||||
|
" 'w+' | destroy contents | create new |\n"
|
||||||
|
" 'a+' | write to end | create new |\n"
|
||||||
|
"") {
|
||||||
|
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
||||||
@ -181,7 +195,10 @@ DEF(_fileOpen, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fileRead, "") {
|
DEF(_fileRead,
|
||||||
|
"io.File.read(count:Number) -> String",
|
||||||
|
"Reads [count] number of bytes from the file and return it as String."
|
||||||
|
"If the count is -1 it'll read till the end of file and return it.") {
|
||||||
|
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
if (!pkCheckArgcRange(vm, argc, 0, 1)) return;
|
if (!pkCheckArgcRange(vm, argc, 0, 1)) return;
|
||||||
@ -265,7 +282,10 @@ L_done:
|
|||||||
|
|
||||||
// Note that fgetline is not standard in older version of C. so we're defining
|
// Note that fgetline is not standard in older version of C. so we're defining
|
||||||
// something similler.
|
// something similler.
|
||||||
DEF(_fileGetLine, "") {
|
DEF(_fileGetLine,
|
||||||
|
"io.File.getline() -> String",
|
||||||
|
"Reads a line from the file and return it as string. This function can only "
|
||||||
|
"be used for files that are opened with text mode.") {
|
||||||
File* file = (File*) pkGetSelf(vm);
|
File* file = (File*) pkGetSelf(vm);
|
||||||
|
|
||||||
if (file->closed) {
|
if (file->closed) {
|
||||||
@ -316,7 +336,10 @@ L_done:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fileWrite, "") {
|
DEF(_fileWrite,
|
||||||
|
"io.File.write(data:String) -> Null",
|
||||||
|
"Write the [data] to the file. Since pocketlang string support any valid"
|
||||||
|
"byte value in it's string, binary data can also be written with strings.") {
|
||||||
|
|
||||||
File* file = (File*) pkGetSelf(vm);
|
File* file = (File*) pkGetSelf(vm);
|
||||||
const char* text; uint32_t length;
|
const char* text; uint32_t length;
|
||||||
@ -342,7 +365,9 @@ DEF(_fileWrite, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fileClose, "") {
|
DEF(_fileClose,
|
||||||
|
"io.File.close()",
|
||||||
|
"Closes the opend file.") {
|
||||||
|
|
||||||
File* file = (File*) pkGetSelf(vm);
|
File* file = (File*) pkGetSelf(vm);
|
||||||
|
|
||||||
@ -362,8 +387,12 @@ DEF(_fileClose, "") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fileSeek,
|
DEF(_fileSeek,
|
||||||
"io.File.seek(offset:int, whence:int) -> null\n"
|
"io.File.seek(offset:Number, whence:Number) -> Null",
|
||||||
"") {
|
"Move the file read/write offset. where [offset] is the offset from "
|
||||||
|
"[whence] which should be any of the bellow three.\n"
|
||||||
|
" 0: Begining of the file.\n"
|
||||||
|
" 1: Current position.\n"
|
||||||
|
" 2: End of the file.") {
|
||||||
|
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
||||||
@ -392,7 +421,9 @@ DEF(_fileSeek,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_fileTell, "") {
|
DEF(_fileTell,
|
||||||
|
"io.File.tell() -> Number",
|
||||||
|
"Returns the read/write position of the file.") {
|
||||||
File* file = (File*) pkGetSelf(vm);
|
File* file = (File*) pkGetSelf(vm);
|
||||||
|
|
||||||
if (file->closed) {
|
if (file->closed) {
|
||||||
@ -404,11 +435,22 @@ DEF(_fileTell, "") {
|
|||||||
pkSetSlotNumber(vm, 0, (double) ftell(file->fp));
|
pkSetSlotNumber(vm, 0, (double) ftell(file->fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// open(path, mode='r') is equal to:
|
// TODO: The docstring is copyied from io.File.open() this violates DRY.
|
||||||
//
|
DEF(_open,
|
||||||
// from io import File
|
"open(path:String, mode:String) -> Null",
|
||||||
// return File().open(path, mode)
|
"Opens a file at the [path] with the [mode]. Path should be either "
|
||||||
DEF(_open, NULL /* == _fileOpen */) {
|
"absolute or relative to the current working directory. and [mode] can be"
|
||||||
|
"'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).\n"
|
||||||
|
"\n"
|
||||||
|
" mode | If already exists | If does not exist |\n"
|
||||||
|
" -----+-------------------+-------------------|\n"
|
||||||
|
" 'r' | read from start | failure to open |\n"
|
||||||
|
" 'w' | destroy contents | create new |\n"
|
||||||
|
" 'a' | write to end | create new |\n"
|
||||||
|
" 'r+' | read from start | error |\n"
|
||||||
|
" 'w+' | destroy contents | create new |\n"
|
||||||
|
" 'a+' | write to end | create new |\n"
|
||||||
|
"") {
|
||||||
pkReserveSlots(vm, 3);
|
pkReserveSlots(vm, 3);
|
||||||
|
|
||||||
// slots[1] = path
|
// slots[1] = path
|
||||||
@ -431,7 +473,7 @@ void registerModuleIO(PKVM* vm) {
|
|||||||
|
|
||||||
PkHandle* io = pkNewModule(vm, "io");
|
PkHandle* io = pkNewModule(vm, "io");
|
||||||
|
|
||||||
pkRegisterBuiltinFn(vm, "open", _open, -1, DOCSTRING(_fileOpen));
|
pkRegisterBuiltinFn(vm, "open", _open, -1, DOCSTRING(_open));
|
||||||
|
|
||||||
pkReserveSlots(vm, 2);
|
pkReserveSlots(vm, 2);
|
||||||
pkSetSlotHandle(vm, 0, io); // slot[0] = io
|
pkSetSlotHandle(vm, 0, io); // slot[0] = io
|
||||||
@ -442,24 +484,27 @@ void registerModuleIO(PKVM* vm) {
|
|||||||
pkSetSlotNumber(vm, 1, 2); // slot[1] = 2
|
pkSetSlotNumber(vm, 1, 2); // slot[1] = 2
|
||||||
pkSetAttribute(vm, 0, "stderr", 1); // slot[0].stderr = slot[1]
|
pkSetAttribute(vm, 0, "stderr", 1); // slot[0].stderr = slot[1]
|
||||||
|
|
||||||
pkModuleAddFunction(vm, io, "write", _ioWrite, 2);
|
REGISTER_FN(io, "write", _ioWrite, 2);
|
||||||
pkModuleAddFunction(vm, io, "flush", _ioFlush, 0);
|
REGISTER_FN(io, "flush", _ioFlush, 0);
|
||||||
pkModuleAddFunction(vm, io, "getc", _ioGetc, 0);
|
REGISTER_FN(io, "getc", _ioGetc, 0);
|
||||||
|
|
||||||
PkHandle* cls_file = pkNewClass(vm, "File", NULL, io, _fileNew, _fileDelete);
|
PkHandle* cls_file = pkNewClass(vm, "File", NULL, io,
|
||||||
pkClassAddMethod(vm, cls_file, "open", _fileOpen, -1);
|
_fileNew, _fileDelete,
|
||||||
pkClassAddMethod(vm, cls_file, "read", _fileRead, -1);
|
"A simple file type.");
|
||||||
pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1);
|
|
||||||
pkClassAddMethod(vm, cls_file, "getline", _fileGetLine, 0);
|
ADD_METHOD(cls_file, "open", _fileOpen, -1);
|
||||||
pkClassAddMethod(vm, cls_file, "close", _fileClose, 0);
|
ADD_METHOD(cls_file, "read", _fileRead, -1);
|
||||||
pkClassAddMethod(vm, cls_file, "seek", _fileSeek, -1);
|
ADD_METHOD(cls_file, "write", _fileWrite, 1);
|
||||||
pkClassAddMethod(vm, cls_file, "tell", _fileTell, 0);
|
ADD_METHOD(cls_file, "getline", _fileGetLine, 0);
|
||||||
|
ADD_METHOD(cls_file, "close", _fileClose, 0);
|
||||||
|
ADD_METHOD(cls_file, "seek", _fileSeek, -1);
|
||||||
|
ADD_METHOD(cls_file, "tell", _fileTell, 0);
|
||||||
pkReleaseHandle(vm, cls_file);
|
pkReleaseHandle(vm, cls_file);
|
||||||
|
|
||||||
// A convinent function to read file by io.readfile(path).
|
// A convinent function to read file by io.readfile(path).
|
||||||
pkModuleAddSource(vm, io,
|
pkModuleAddSource(vm, io,
|
||||||
"## Reads a file and return it's content as string.\n"
|
|
||||||
"def readfile(filepath)\n"
|
"def readfile(filepath)\n"
|
||||||
|
" \"Reads a file and return it's content as string\""
|
||||||
" fp = File()\n"
|
" fp = File()\n"
|
||||||
" fp.open(filepath, 'r')\n"
|
" fp.open(filepath, 'r')\n"
|
||||||
" text = fp.read()\n"
|
" text = fp.read()\n"
|
||||||
|
@ -160,7 +160,7 @@ static cJSON* _pocketToCJson(PKVM* vm, Var item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_jsonParse,
|
DEF(_jsonParse,
|
||||||
"json.parse(json_str:String) -> var\n"
|
"json.parse(json_str:String) -> Var",
|
||||||
"Parse a json string into pocket lang object.") {
|
"Parse a json string into pocket lang object.") {
|
||||||
|
|
||||||
const char* string;
|
const char* string;
|
||||||
@ -186,7 +186,7 @@ DEF(_jsonParse,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_jsonPrint,
|
DEF(_jsonPrint,
|
||||||
"json.print(value:Var[, pretty:Bool=false])\n"
|
"json.print(value:Var, pretty:Bool=false)",
|
||||||
"Render a pocketlang value into text. Takes an optional argument pretty, if "
|
"Render a pocketlang value into text. Takes an optional argument pretty, if "
|
||||||
"true it'll pretty print the output.") {
|
"true it'll pretty print the output.") {
|
||||||
|
|
||||||
@ -225,8 +225,8 @@ DEF(_jsonPrint,
|
|||||||
void registerModuleJson(PKVM* vm) {
|
void registerModuleJson(PKVM* vm) {
|
||||||
PkHandle* json = pkNewModule(vm, "json");
|
PkHandle* json = pkNewModule(vm, "json");
|
||||||
|
|
||||||
pkModuleAddFunction(vm, json, "parse", _jsonParse, 1);
|
REGISTER_FN(json, "parse", _jsonParse, 1);
|
||||||
pkModuleAddFunction(vm, json, "print", _jsonPrint, -1);
|
REGISTER_FN(json, "print", _jsonPrint, -1);
|
||||||
|
|
||||||
pkRegisterModule(vm, json);
|
pkRegisterModule(vm, json);
|
||||||
pkReleaseHandle(vm, json);
|
pkReleaseHandle(vm, json);
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
#define PK_PI 3.14159265358979323846
|
#define PK_PI 3.14159265358979323846
|
||||||
|
|
||||||
DEF(stdMathFloor,
|
DEF(stdMathFloor,
|
||||||
"floor(value:num) -> num\n") {
|
"math.floor(value:Numberber) -> Numberber",
|
||||||
|
"Return the floor value.") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
||||||
@ -22,7 +23,8 @@ DEF(stdMathFloor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathCeil,
|
DEF(stdMathCeil,
|
||||||
"ceil(value:num) -> num\n") {
|
"math.ceil(value:Number) -> Number",
|
||||||
|
"Returns the ceiling value.") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
||||||
@ -30,7 +32,8 @@ DEF(stdMathCeil,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathPow,
|
DEF(stdMathPow,
|
||||||
"pow(a:num, b:num) -> num\n") {
|
"math.pow(a:Number, b:Number) -> Number",
|
||||||
|
"Returns the power 'b' of 'a' similler to a**b.") {
|
||||||
|
|
||||||
double num, ex;
|
double num, ex;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
||||||
@ -39,7 +42,8 @@ DEF(stdMathPow,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathSqrt,
|
DEF(stdMathSqrt,
|
||||||
"sqrt(value:num) -> num\n") {
|
"math.sqrt(value:Number) -> Number",
|
||||||
|
"Returns the square root of the value") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
||||||
@ -47,7 +51,8 @@ DEF(stdMathSqrt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathAbs,
|
DEF(stdMathAbs,
|
||||||
"abs(value:num) -> num\n") {
|
"math.abs(value:Number) -> Number",
|
||||||
|
"Returns the absolute value.") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
||||||
@ -56,7 +61,8 @@ DEF(stdMathAbs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathSign,
|
DEF(stdMathSign,
|
||||||
"sign(value:num) -> num\n") {
|
"math.sign(value:Number) -> Number",
|
||||||
|
"return the sign of the which is one of (+1, 0, -1).") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
||||||
@ -67,7 +73,7 @@ DEF(stdMathSign,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathSine,
|
DEF(stdMathSine,
|
||||||
"sin(rad:num) -> num\n"
|
"math.sin(rad:Number) -> Number",
|
||||||
"Return the sine value of the argument [rad] which is an angle expressed "
|
"Return the sine value of the argument [rad] which is an angle expressed "
|
||||||
"in radians.") {
|
"in radians.") {
|
||||||
|
|
||||||
@ -77,7 +83,7 @@ DEF(stdMathSine,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathCosine,
|
DEF(stdMathCosine,
|
||||||
"cos(rad:num) -> num\n"
|
"math.cos(rad:Number) -> Number",
|
||||||
"Return the cosine value of the argument [rad] which is an angle expressed "
|
"Return the cosine value of the argument [rad] which is an angle expressed "
|
||||||
"in radians.") {
|
"in radians.") {
|
||||||
|
|
||||||
@ -87,7 +93,7 @@ DEF(stdMathCosine,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathTangent,
|
DEF(stdMathTangent,
|
||||||
"tan(rad:num) -> num\n"
|
"math.tan(rad:Number) -> Number",
|
||||||
"Return the tangent value of the argument [rad] which is an angle expressed "
|
"Return the tangent value of the argument [rad] which is an angle expressed "
|
||||||
"in radians.") {
|
"in radians.") {
|
||||||
|
|
||||||
@ -97,7 +103,7 @@ DEF(stdMathTangent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathSinh,
|
DEF(stdMathSinh,
|
||||||
"sinh(val) -> val\n"
|
"math.sinh(val:Number) -> Number",
|
||||||
"Return the hyperbolic sine value of the argument [val].") {
|
"Return the hyperbolic sine value of the argument [val].") {
|
||||||
|
|
||||||
double val;
|
double val;
|
||||||
@ -106,7 +112,7 @@ DEF(stdMathSinh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathCosh,
|
DEF(stdMathCosh,
|
||||||
"cosh(val) -> val\n"
|
"math.cosh(val:Number) -> Number",
|
||||||
"Return the hyperbolic cosine value of the argument [val].") {
|
"Return the hyperbolic cosine value of the argument [val].") {
|
||||||
|
|
||||||
double val;
|
double val;
|
||||||
@ -115,7 +121,7 @@ DEF(stdMathCosh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathTanh,
|
DEF(stdMathTanh,
|
||||||
"tanh(val) -> val\n"
|
"math.tanh(val:Number) -> Number",
|
||||||
"Return the hyperbolic tangent value of the argument [val].") {
|
"Return the hyperbolic tangent value of the argument [val].") {
|
||||||
|
|
||||||
double val;
|
double val;
|
||||||
@ -124,7 +130,7 @@ DEF(stdMathTanh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathArcSine,
|
DEF(stdMathArcSine,
|
||||||
"asin(num) -> num\n"
|
"math.asin(num:Number) -> Number",
|
||||||
"Return the arcsine value of the argument [num] which is an angle "
|
"Return the arcsine value of the argument [num] which is an angle "
|
||||||
"expressed in radians.") {
|
"expressed in radians.") {
|
||||||
|
|
||||||
@ -139,7 +145,7 @@ DEF(stdMathArcSine,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathArcCosine,
|
DEF(stdMathArcCosine,
|
||||||
"acos(num) -> num\n"
|
"math.acos(num:Number) -> Number",
|
||||||
"Return the arc cosine value of the argument [num] which is "
|
"Return the arc cosine value of the argument [num] which is "
|
||||||
"an angle expressed in radians.") {
|
"an angle expressed in radians.") {
|
||||||
|
|
||||||
@ -154,7 +160,7 @@ DEF(stdMathArcCosine,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathArcTangent,
|
DEF(stdMathArcTangent,
|
||||||
"atan(num) -> num\n"
|
"math.atan(num:Number) -> Number",
|
||||||
"Return the arc tangent value of the argument [num] which is "
|
"Return the arc tangent value of the argument [num] which is "
|
||||||
"an angle expressed in radians.") {
|
"an angle expressed in radians.") {
|
||||||
|
|
||||||
@ -164,7 +170,7 @@ DEF(stdMathArcTangent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathLog10,
|
DEF(stdMathLog10,
|
||||||
"log10(value:num) -> num\n"
|
"math.log10(value:Number) -> Number",
|
||||||
"Return the logarithm to base 10 of argument [value]") {
|
"Return the logarithm to base 10 of argument [value]") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
@ -173,7 +179,7 @@ DEF(stdMathLog10,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathRound,
|
DEF(stdMathRound,
|
||||||
"round(value:num) -> num\n"
|
"math.round(value:Number) -> Number",
|
||||||
"Round to nearest integer, away from zero and return the number.") {
|
"Round to nearest integer, away from zero and return the number.") {
|
||||||
|
|
||||||
double num;
|
double num;
|
||||||
@ -182,7 +188,7 @@ DEF(stdMathRound,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(stdMathRand,
|
DEF(stdMathRand,
|
||||||
"rand() -> num\n"
|
"math.rand() -> Number",
|
||||||
"Return a random runber in the range of 0..0x7fff.") {
|
"Return a random runber in the range of 0..0x7fff.") {
|
||||||
|
|
||||||
// RAND_MAX is implementation dependent but is guaranteed to be at least
|
// RAND_MAX is implementation dependent but is guaranteed to be at least
|
||||||
@ -205,24 +211,24 @@ void registerModuleMath(PKVM* vm) {
|
|||||||
pkSetSlotNumber(vm, 1, PK_PI); // slot[1] = 3.14
|
pkSetSlotNumber(vm, 1, PK_PI); // slot[1] = 3.14
|
||||||
pkSetAttribute(vm, 0, "PI", 1); // slot[0].PI = slot[1]
|
pkSetAttribute(vm, 0, "PI", 1); // slot[0].PI = slot[1]
|
||||||
|
|
||||||
pkModuleAddFunction(vm, math, "floor", stdMathFloor, 1);
|
REGISTER_FN(math, "floor", stdMathFloor, 1);
|
||||||
pkModuleAddFunction(vm, math, "ceil", stdMathCeil, 1);
|
REGISTER_FN(math, "ceil", stdMathCeil, 1);
|
||||||
pkModuleAddFunction(vm, math, "pow", stdMathPow, 2);
|
REGISTER_FN(math, "pow", stdMathPow, 2);
|
||||||
pkModuleAddFunction(vm, math, "sqrt", stdMathSqrt, 1);
|
REGISTER_FN(math, "sqrt", stdMathSqrt, 1);
|
||||||
pkModuleAddFunction(vm, math, "abs", stdMathAbs, 1);
|
REGISTER_FN(math, "abs", stdMathAbs, 1);
|
||||||
pkModuleAddFunction(vm, math, "sign", stdMathSign, 1);
|
REGISTER_FN(math, "sign", stdMathSign, 1);
|
||||||
pkModuleAddFunction(vm, math, "sin", stdMathSine, 1);
|
REGISTER_FN(math, "sin", stdMathSine, 1);
|
||||||
pkModuleAddFunction(vm, math, "cos", stdMathCosine, 1);
|
REGISTER_FN(math, "cos", stdMathCosine, 1);
|
||||||
pkModuleAddFunction(vm, math, "tan", stdMathTangent, 1);
|
REGISTER_FN(math, "tan", stdMathTangent, 1);
|
||||||
pkModuleAddFunction(vm, math, "sinh", stdMathSinh, 1);
|
REGISTER_FN(math, "sinh", stdMathSinh, 1);
|
||||||
pkModuleAddFunction(vm, math, "cosh", stdMathCosh, 1);
|
REGISTER_FN(math, "cosh", stdMathCosh, 1);
|
||||||
pkModuleAddFunction(vm, math, "tanh", stdMathTanh, 1);
|
REGISTER_FN(math, "tanh", stdMathTanh, 1);
|
||||||
pkModuleAddFunction(vm, math, "asin", stdMathArcSine, 1);
|
REGISTER_FN(math, "asin", stdMathArcSine, 1);
|
||||||
pkModuleAddFunction(vm, math, "acos", stdMathArcCosine, 1);
|
REGISTER_FN(math, "acos", stdMathArcCosine, 1);
|
||||||
pkModuleAddFunction(vm, math, "atan", stdMathArcTangent, 1);
|
REGISTER_FN(math, "atan", stdMathArcTangent, 1);
|
||||||
pkModuleAddFunction(vm, math, "log10", stdMathLog10, 1);
|
REGISTER_FN(math, "log10", stdMathLog10, 1);
|
||||||
pkModuleAddFunction(vm, math, "round", stdMathRound, 1);
|
REGISTER_FN(math, "round", stdMathRound, 1);
|
||||||
pkModuleAddFunction(vm, math, "rand", stdMathRand, 0);
|
REGISTER_FN(math, "rand", stdMathRand, 0);
|
||||||
|
|
||||||
pkRegisterModule(vm, math);
|
pkRegisterModule(vm, math);
|
||||||
pkReleaseHandle(vm, math);
|
pkReleaseHandle(vm, math);
|
||||||
|
@ -175,7 +175,7 @@ bool osGetExeFilePath(char* buff, int size) {
|
|||||||
|
|
||||||
// Yes both 'os' and 'path' have getcwd functions.
|
// Yes both 'os' and 'path' have getcwd functions.
|
||||||
DEF(_osGetCWD,
|
DEF(_osGetCWD,
|
||||||
"os.getcwd() -> String\n"
|
"os.getcwd() -> String",
|
||||||
"Returns the current working directory") {
|
"Returns the current working directory") {
|
||||||
char cwd[MAX_PATH_LEN];
|
char cwd[MAX_PATH_LEN];
|
||||||
if (getcwd(cwd, sizeof(cwd)) == NULL) {
|
if (getcwd(cwd, sizeof(cwd)) == NULL) {
|
||||||
@ -185,7 +185,7 @@ DEF(_osGetCWD,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osChdir,
|
DEF(_osChdir,
|
||||||
"os.chdir(path:String)\n"
|
"os.chdir(path:String)",
|
||||||
"Change the current working directory") {
|
"Change the current working directory") {
|
||||||
|
|
||||||
const char* path;
|
const char* path;
|
||||||
@ -195,7 +195,7 @@ DEF(_osChdir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osMkdir,
|
DEF(_osMkdir,
|
||||||
"os.mkdir(path:String)\n"
|
"os.mkdir(path:String)",
|
||||||
"Creates a directory at the path. The path should be valid.") {
|
"Creates a directory at the path. The path should be valid.") {
|
||||||
|
|
||||||
const char* path;
|
const char* path;
|
||||||
@ -213,7 +213,7 @@ DEF(_osMkdir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osRmdir,
|
DEF(_osRmdir,
|
||||||
"os.rmdir(path:String)\n"
|
"os.rmdir(path:String)",
|
||||||
"Removes an empty directory at the path.") {
|
"Removes an empty directory at the path.") {
|
||||||
|
|
||||||
const char* path;
|
const char* path;
|
||||||
@ -222,7 +222,7 @@ DEF(_osRmdir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osUnlink,
|
DEF(_osUnlink,
|
||||||
"os.rmdir(path:String)\n"
|
"os.rmdir(path:String)",
|
||||||
"Removes a file at the path.") {
|
"Removes a file at the path.") {
|
||||||
|
|
||||||
const char* path;
|
const char* path;
|
||||||
@ -231,7 +231,7 @@ DEF(_osUnlink,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osModitime,
|
DEF(_osModitime,
|
||||||
"os.moditime(path:String) -> Number\n"
|
"os.moditime(path:String) -> Number",
|
||||||
"Returns the modified timestamp of the file.") {
|
"Returns the modified timestamp of the file.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
@ -243,7 +243,7 @@ DEF(_osModitime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osFileSize,
|
DEF(_osFileSize,
|
||||||
"os.filesize(path:String) -> Number\n"
|
"os.filesize(path:String) -> Number",
|
||||||
"Returns the file size in bytes.") {
|
"Returns the file size in bytes.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ DEF(_osFileSize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osSystem,
|
DEF(_osSystem,
|
||||||
"os.system(cmd:String) -> Number\n"
|
"os.system(cmd:String) -> Number",
|
||||||
"Execute the command in a subprocess, Returns the exit code of the child "
|
"Execute the command in a subprocess, Returns the exit code of the child "
|
||||||
"process.") {
|
"process.") {
|
||||||
const char* cmd;
|
const char* cmd;
|
||||||
@ -278,7 +278,7 @@ DEF(_osSystem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osGetenv,
|
DEF(_osGetenv,
|
||||||
"os.getenv(name:String) -> String\n"
|
"os.getenv(name:String) -> String",
|
||||||
"Returns the environment variable as String if it exists otherwise it'll "
|
"Returns the environment variable as String if it exists otherwise it'll "
|
||||||
"return null.") {
|
"return null.") {
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ DEF(_osGetenv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_osExepath,
|
DEF(_osExepath,
|
||||||
"os.exepath() -> String\n"
|
"os.exepath() -> String",
|
||||||
"Returns the path of the pocket interpreter executable.") {
|
"Returns the path of the pocket interpreter executable.") {
|
||||||
|
|
||||||
char buff[MAX_PATH_LEN];
|
char buff[MAX_PATH_LEN];
|
||||||
@ -320,16 +320,16 @@ void registerModuleOS(PKVM* vm) {
|
|||||||
pkSetSlotString(vm, 1, OS_NAME); // slots[1] = "windows"
|
pkSetSlotString(vm, 1, OS_NAME); // slots[1] = "windows"
|
||||||
pkSetAttribute(vm, 0, "NAME", 1); // os.NAME = "windows"
|
pkSetAttribute(vm, 0, "NAME", 1); // os.NAME = "windows"
|
||||||
|
|
||||||
pkModuleAddFunction(vm, os, "getcwd", _osGetCWD, 0);
|
REGISTER_FN(os, "getcwd", _osGetCWD, 0);
|
||||||
pkModuleAddFunction(vm, os, "chdir", _osChdir, 1);
|
REGISTER_FN(os, "chdir", _osChdir, 1);
|
||||||
pkModuleAddFunction(vm, os, "mkdir", _osMkdir, 1);
|
REGISTER_FN(os, "mkdir", _osMkdir, 1);
|
||||||
pkModuleAddFunction(vm, os, "rmdir", _osRmdir, 1);
|
REGISTER_FN(os, "rmdir", _osRmdir, 1);
|
||||||
pkModuleAddFunction(vm, os, "unlink", _osUnlink, 1);
|
REGISTER_FN(os, "unlink", _osUnlink, 1);
|
||||||
pkModuleAddFunction(vm, os, "moditime", _osModitime, 1);
|
REGISTER_FN(os, "moditime", _osModitime, 1);
|
||||||
pkModuleAddFunction(vm, os, "filesize", _osFileSize, 1);
|
REGISTER_FN(os, "filesize", _osFileSize, 1);
|
||||||
pkModuleAddFunction(vm, os, "system", _osSystem, 1);
|
REGISTER_FN(os, "system", _osSystem, 1);
|
||||||
pkModuleAddFunction(vm, os, "getenv", _osGetenv, 1);
|
REGISTER_FN(os, "getenv", _osGetenv, 1);
|
||||||
pkModuleAddFunction(vm, os, "exepath", _osExepath, 0);
|
REGISTER_FN(os, "exepath", _osExepath, 0);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Implement makedirs which recursively mkdir().
|
// - Implement makedirs which recursively mkdir().
|
||||||
|
@ -225,7 +225,9 @@ static inline size_t pathAbs(const char* path, char* buff, size_t buffsz) {
|
|||||||
/* PATH MODULE FUNCTIONS */
|
/* PATH MODULE FUNCTIONS */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
DEF(_pathGetCWD, "") {
|
DEF(_pathGetCWD,
|
||||||
|
"path.getcwd() -> String",
|
||||||
|
"Returns the current working directory.") {
|
||||||
char cwd[MAX_PATH_LEN];
|
char cwd[MAX_PATH_LEN];
|
||||||
if (getcwd(cwd, sizeof(cwd)) == NULL) {
|
if (getcwd(cwd, sizeof(cwd)) == NULL) {
|
||||||
// TODO: Handle error.
|
// TODO: Handle error.
|
||||||
@ -233,7 +235,9 @@ DEF(_pathGetCWD, "") {
|
|||||||
pkSetSlotString(vm, 0, cwd);
|
pkSetSlotString(vm, 0, cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathAbspath, "") {
|
DEF(_pathAbspath,
|
||||||
|
"path.abspath(path:String) -> String",
|
||||||
|
"Returns the absolute path of the [path].") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
|
|
||||||
@ -242,7 +246,10 @@ DEF(_pathAbspath, "") {
|
|||||||
pkSetSlotStringLength(vm, 0, abspath, len);
|
pkSetSlotStringLength(vm, 0, abspath, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathRelpath, "") {
|
DEF(_pathRelpath,
|
||||||
|
"path.relpath(path:String, from:String) -> String",
|
||||||
|
"Returns the relative path of the [path] argument from the [from] "
|
||||||
|
"directory.") {
|
||||||
const char* path, * from;
|
const char* path, * from;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
if (!pkValidateSlotString(vm, 2, &from, NULL)) return;
|
if (!pkValidateSlotString(vm, 2, &from, NULL)) return;
|
||||||
@ -259,7 +266,10 @@ DEF(_pathRelpath, "") {
|
|||||||
pkSetSlotStringLength(vm, 0, result, len);
|
pkSetSlotStringLength(vm, 0, result, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathJoin, "") {
|
DEF(_pathJoin,
|
||||||
|
"path.join(...) -> String",
|
||||||
|
"Joins path with path seperator and return it. The maximum count of paths "
|
||||||
|
"which can be joined for a call is " TOSTRING(MAX_JOIN_PATHS) ".") {
|
||||||
const char* paths[MAX_JOIN_PATHS + 1]; // +1 for NULL.
|
const char* paths[MAX_JOIN_PATHS + 1]; // +1 for NULL.
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
|
|
||||||
@ -280,7 +290,9 @@ DEF(_pathJoin, "") {
|
|||||||
pkSetSlotStringLength(vm, 0, result, len);
|
pkSetSlotStringLength(vm, 0, result, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathNormpath, "") {
|
DEF(_pathNormpath,
|
||||||
|
"path.normpath(path:String) -> String",
|
||||||
|
"Returns the normalized path of the [path].") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
|
|
||||||
@ -289,7 +301,9 @@ DEF(_pathNormpath, "") {
|
|||||||
pkSetSlotStringLength(vm, 0, result, len);
|
pkSetSlotStringLength(vm, 0, result, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathBaseName, "") {
|
DEF(_pathBaseName,
|
||||||
|
"path.basename(path:String) -> String",
|
||||||
|
"Returns the final component for the path") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
|
|
||||||
@ -299,7 +313,9 @@ DEF(_pathBaseName, "") {
|
|||||||
pkSetSlotStringLength(vm, 0, base_name, (uint32_t)length);
|
pkSetSlotStringLength(vm, 0, base_name, (uint32_t)length);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathDirName, "") {
|
DEF(_pathDirName,
|
||||||
|
"path.dirname(path:String) -> String",
|
||||||
|
"Returns the directory of the path.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
|
|
||||||
@ -308,14 +324,18 @@ DEF(_pathDirName, "") {
|
|||||||
pkSetSlotStringLength(vm, 0, path, (uint32_t)length);
|
pkSetSlotStringLength(vm, 0, path, (uint32_t)length);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathIsPathAbs, "") {
|
DEF(_pathIsPathAbs,
|
||||||
|
"path.isabspath(path:String) -> Bool",
|
||||||
|
"Returns true if the path is absolute otherwise false.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
|
|
||||||
pkSetSlotBool(vm, 0, cwk_path_is_absolute(path));
|
pkSetSlotBool(vm, 0, cwk_path_is_absolute(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathGetExtension, "") {
|
DEF(_pathGetExtension,
|
||||||
|
"path.getext(path:String) -> String",
|
||||||
|
"Returns the file extension of the path.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
|
|
||||||
@ -328,25 +348,33 @@ DEF(_pathGetExtension, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathExists, "") {
|
DEF(_pathExists,
|
||||||
|
"path.exists(path:String) -> String",
|
||||||
|
"Returns true if the file exists.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
pkSetSlotBool(vm, 0, pathIsExists(path));
|
pkSetSlotBool(vm, 0, pathIsExists(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathIsFile, "") {
|
DEF(_pathIsFile,
|
||||||
|
"path.isfile(path:String) -> Bool",
|
||||||
|
"Returns true if the path is a file.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
pkSetSlotBool(vm, 0, pathIsFile(path));
|
pkSetSlotBool(vm, 0, pathIsFile(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathIsDir, "") {
|
DEF(_pathIsDir,
|
||||||
|
"path.isdir(path:String) -> Bool",
|
||||||
|
"Returns true if the path is a directory.") {
|
||||||
const char* path;
|
const char* path;
|
||||||
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
if (!pkValidateSlotString(vm, 1, &path, NULL)) return;
|
||||||
pkSetSlotBool(vm, 0, pathIsDir(path));
|
pkSetSlotBool(vm, 0, pathIsDir(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_pathListDir, "") {
|
DEF(_pathListDir,
|
||||||
|
"path.listdir(path:String='.') -> List",
|
||||||
|
"Returns all the entries in the directory at the [path].") {
|
||||||
|
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
if (!pkCheckArgcRange(vm, argc, 0, 1)) return;
|
if (!pkCheckArgcRange(vm, argc, 0, 1)) return;
|
||||||
@ -411,19 +439,19 @@ void registerModulePath(PKVM* vm) {
|
|||||||
|
|
||||||
PkHandle* path = pkNewModule(vm, "path");
|
PkHandle* path = pkNewModule(vm, "path");
|
||||||
|
|
||||||
pkModuleAddFunction(vm, path, "getcwd", _pathGetCWD, 0);
|
REGISTER_FN(path, "getcwd", _pathGetCWD, 0);
|
||||||
pkModuleAddFunction(vm, path, "abspath", _pathAbspath, 1);
|
REGISTER_FN(path, "abspath", _pathAbspath, 1);
|
||||||
pkModuleAddFunction(vm, path, "relpath", _pathRelpath, 2);
|
REGISTER_FN(path, "relpath", _pathRelpath, 2);
|
||||||
pkModuleAddFunction(vm, path, "join", _pathJoin, -1);
|
REGISTER_FN(path, "join", _pathJoin, -1);
|
||||||
pkModuleAddFunction(vm, path, "normpath", _pathNormpath, 1);
|
REGISTER_FN(path, "normpath", _pathNormpath, 1);
|
||||||
pkModuleAddFunction(vm, path, "basename", _pathBaseName, 1);
|
REGISTER_FN(path, "basename", _pathBaseName, 1);
|
||||||
pkModuleAddFunction(vm, path, "dirname", _pathDirName, 1);
|
REGISTER_FN(path, "dirname", _pathDirName, 1);
|
||||||
pkModuleAddFunction(vm, path, "isabspath", _pathIsPathAbs, 1);
|
REGISTER_FN(path, "isabspath", _pathIsPathAbs, 1);
|
||||||
pkModuleAddFunction(vm, path, "getext", _pathGetExtension, 1);
|
REGISTER_FN(path, "getext", _pathGetExtension, 1);
|
||||||
pkModuleAddFunction(vm, path, "exists", _pathExists, 1);
|
REGISTER_FN(path, "exists", _pathExists, 1);
|
||||||
pkModuleAddFunction(vm, path, "isfile", _pathIsFile, 1);
|
REGISTER_FN(path, "isfile", _pathIsFile, 1);
|
||||||
pkModuleAddFunction(vm, path, "isdir", _pathIsDir, 1);
|
REGISTER_FN(path, "isdir", _pathIsDir, 1);
|
||||||
pkModuleAddFunction(vm, path, "listdir", _pathListDir, -1);
|
REGISTER_FN(path, "listdir", _pathListDir, -1);
|
||||||
|
|
||||||
pkRegisterModule(vm, path);
|
pkRegisterModule(vm, path);
|
||||||
pkReleaseHandle(vm, path);
|
pkReleaseHandle(vm, path);
|
||||||
|
@ -19,20 +19,20 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF(_timeEpoch,
|
DEF(_timeEpoch,
|
||||||
"time() -> num\n"
|
"time() -> Number",
|
||||||
"Returns the number of seconds since the Epoch, 1970-01-01 "
|
"Returns the number of seconds since the Epoch, 1970-01-01 "
|
||||||
"00:00:00 +0000 (UTC).") {
|
"00:00:00 +0000 (UTC).") {
|
||||||
pkSetSlotNumber(vm, 0, (double) time(NULL));
|
pkSetSlotNumber(vm, 0, (double) time(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_timeClock,
|
DEF(_timeClock,
|
||||||
"clock() -> num\n"
|
"clock() -> Number",
|
||||||
"Returns the number of clocks passed divied by CLOCKS_PER_SEC.") {
|
"Returns the number of clocks passed divied by CLOCKS_PER_SEC.") {
|
||||||
pkSetSlotNumber(vm, 0, (double) clock() / CLOCKS_PER_SEC);
|
pkSetSlotNumber(vm, 0, (double) clock() / CLOCKS_PER_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_timeSleep,
|
DEF(_timeSleep,
|
||||||
"sleep(t:num) -> num\n"
|
"sleep(t:num) -> Number",
|
||||||
"Sleep for [t] milliseconds.") {
|
"Sleep for [t] milliseconds.") {
|
||||||
|
|
||||||
double t;
|
double t;
|
||||||
@ -54,9 +54,9 @@ DEF(_timeSleep,
|
|||||||
void registerModuleTime(PKVM* vm) {
|
void registerModuleTime(PKVM* vm) {
|
||||||
PkHandle* time = pkNewModule(vm, "time");
|
PkHandle* time = pkNewModule(vm, "time");
|
||||||
|
|
||||||
pkModuleAddFunction(vm, time, "epoch", _timeEpoch, 0);
|
REGISTER_FN(time, "epoch", _timeEpoch, 0);
|
||||||
pkModuleAddFunction(vm, time, "sleep", _timeSleep, 1);
|
REGISTER_FN(time, "sleep", _timeSleep, 1);
|
||||||
pkModuleAddFunction(vm, time, "clock", _timeClock, 0);
|
REGISTER_FN(time, "clock", _timeClock, 0);
|
||||||
|
|
||||||
pkRegisterModule(vm, time);
|
pkRegisterModule(vm, time);
|
||||||
pkReleaseHandle(vm, time);
|
pkReleaseHandle(vm, time);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF(_typesHashable,
|
DEF(_typesHashable,
|
||||||
"types.hashable(value:Var) -> Bool\n"
|
"types.hashable(value:Var) -> Bool",
|
||||||
"Returns true if the [value] is hashable.") {
|
"Returns true if the [value] is hashable.") {
|
||||||
|
|
||||||
// Get argument 1 directly.
|
// Get argument 1 directly.
|
||||||
@ -26,7 +26,7 @@ DEF(_typesHashable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF(_typesHash,
|
DEF(_typesHash,
|
||||||
"types.hash(value:Var) -> Number\n"
|
"types.hash(value:Var) -> Number",
|
||||||
"Returns the hash of the [value]") {
|
"Returns the hash of the [value]") {
|
||||||
|
|
||||||
// Get argument 1 directly.
|
// Get argument 1 directly.
|
||||||
@ -56,7 +56,11 @@ static void _bytebuffDelete(PKVM* vm, void* buff) {
|
|||||||
pkRealloc(vm, buff, 0);
|
pkRealloc(vm, buff, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_bytebuffReserve, "") {
|
DEF(_bytebuffReserve,
|
||||||
|
"types.ByteBuffer.reserve(count:Number) -> Null",
|
||||||
|
"Reserve [count] number of bytes internally. This is use full if the final "
|
||||||
|
"size of the buffer is known beforehand to avoid reduce the number of "
|
||||||
|
"re-allocations.") {
|
||||||
double size;
|
double size;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &size)) return;
|
if (!pkValidateSlotNumber(vm, 1, &size)) return;
|
||||||
|
|
||||||
@ -65,7 +69,10 @@ DEF(_bytebuffReserve, "") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buff.fill(data, count)
|
// buff.fill(data, count)
|
||||||
DEF(_bytebuffFill, "") {
|
DEF(_bytebuffFill,
|
||||||
|
"types.ByteBuffer.fill(value:Number) -> Null",
|
||||||
|
"Fill the buffer with the given byte value. Note that the value must be in "
|
||||||
|
"between 0 and 0xff inclusive.") {
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
if (!pkValidateSlotInteger(vm, 1, &n)) return;
|
if (!pkValidateSlotInteger(vm, 1, &n)) return;
|
||||||
if (n < 0x00 || n > 0xff) {
|
if (n < 0x00 || n > 0xff) {
|
||||||
@ -81,14 +88,20 @@ DEF(_bytebuffFill, "") {
|
|||||||
pkByteBufferFill(self, vm, (uint8_t) n, (int) count);
|
pkByteBufferFill(self, vm, (uint8_t) n, (int) count);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_bytebuffClear, "") {
|
DEF(_bytebuffClear,
|
||||||
|
"types.ByteBuffer.clear() -> Null",
|
||||||
|
"Clear the buffer values.") {
|
||||||
// TODO: Should I also zero or reduce the capacity?
|
// TODO: Should I also zero or reduce the capacity?
|
||||||
pkByteBuffer* self = pkGetSelf(vm);
|
pkByteBuffer* self = pkGetSelf(vm);
|
||||||
self->count = 0;
|
self->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the length of bytes were written.
|
// Returns the length of bytes were written.
|
||||||
DEF(_bytebuffWrite, "") {
|
DEF(_bytebuffWrite,
|
||||||
|
"types.ByteBuffer.write(data:Number|String) -> Null",
|
||||||
|
"Writes the data to the buffer. If the [data] is a number that should be in "
|
||||||
|
"between 0 and 0xff inclusively. If the [data] is a string all the bytes "
|
||||||
|
"of the string will be written to the buffer.") {
|
||||||
pkByteBuffer* self = pkGetSelf(vm);
|
pkByteBuffer* self = pkGetSelf(vm);
|
||||||
|
|
||||||
PkVarType type = pkGetSlotType(vm, 1);
|
PkVarType type = pkGetSlotType(vm, 1);
|
||||||
@ -135,7 +148,8 @@ DEF(_bytebuffWrite, "") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_bytebuffSubscriptGet, "") {
|
DEF(_bytebuffSubscriptGet,
|
||||||
|
"types.ByteBuffer.[](index:Number)", "") {
|
||||||
double index;
|
double index;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &index)) return;
|
if (!pkValidateSlotNumber(vm, 1, &index)) return;
|
||||||
if (floor(index) != index) {
|
if (floor(index) != index) {
|
||||||
@ -154,7 +168,8 @@ DEF(_bytebuffSubscriptGet, "") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_bytebuffSubscriptSet, "") {
|
DEF(_bytebuffSubscriptSet,
|
||||||
|
"types.ByteBuffer.[]=(index:Number, value:Number)", "") {
|
||||||
double index, value;
|
double index, value;
|
||||||
if (!pkValidateSlotNumber(vm, 1, &index)) return;
|
if (!pkValidateSlotNumber(vm, 1, &index)) return;
|
||||||
if (!pkValidateSlotNumber(vm, 2, &value)) return;
|
if (!pkValidateSlotNumber(vm, 2, &value)) return;
|
||||||
@ -184,12 +199,16 @@ DEF(_bytebuffSubscriptSet, "") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_bytebuffString, "") {
|
DEF(_bytebuffString,
|
||||||
|
"types.ByteBuffer.string() -> String",
|
||||||
|
"Returns the buffered values as String.") {
|
||||||
pkByteBuffer* self = pkGetSelf(vm);
|
pkByteBuffer* self = pkGetSelf(vm);
|
||||||
pkSetSlotStringLength(vm, 0, self->data, self->count);
|
pkSetSlotStringLength(vm, 0, self->data, self->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_bytebuffCount, "") {
|
DEF(_bytebuffCount,
|
||||||
|
"types.ByteBuffer.count() -> Number",
|
||||||
|
"Returns the number of bytes that have written to the buffer.") {
|
||||||
pkByteBuffer* self = pkGetSelf(vm);
|
pkByteBuffer* self = pkGetSelf(vm);
|
||||||
pkSetSlotNumber(vm, 0, self->count);
|
pkSetSlotNumber(vm, 0, self->count);
|
||||||
}
|
}
|
||||||
@ -212,7 +231,8 @@ static void _vectorDelete(PKVM* vm, void* vec) {
|
|||||||
pkRealloc(vm, vec, 0);
|
pkRealloc(vm, vec, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_vectorInit, "") {
|
DEF(_vectorInit,
|
||||||
|
"types.Vector._init()", "") {
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
if (!pkCheckArgcRange(vm, argc, 0, 3)) return;
|
if (!pkCheckArgcRange(vm, argc, 0, 3)) return;
|
||||||
|
|
||||||
@ -237,7 +257,8 @@ DEF(_vectorInit, "") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_vectorGetter, "") {
|
DEF(_vectorGetter,
|
||||||
|
"types.Vector.@getter()", "") {
|
||||||
const char* name; uint32_t length;
|
const char* name; uint32_t length;
|
||||||
if (!pkValidateSlotString(vm, 1, &name, &length)) return;
|
if (!pkValidateSlotString(vm, 1, &name, &length)) return;
|
||||||
|
|
||||||
@ -256,7 +277,8 @@ DEF(_vectorGetter, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_vectorSetter, "") {
|
DEF(_vectorSetter,
|
||||||
|
"types.Vector.@setter()", "") {
|
||||||
const char* name; uint32_t length;
|
const char* name; uint32_t length;
|
||||||
if (!pkValidateSlotString(vm, 1, &name, &length)) return;
|
if (!pkValidateSlotString(vm, 1, &name, &length)) return;
|
||||||
|
|
||||||
@ -279,7 +301,8 @@ DEF(_vectorSetter, "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF(_vectorRepr, "") {
|
DEF(_vectorRepr,
|
||||||
|
"types.Vector._repr()", "") {
|
||||||
Vector* vec = pkGetSelf(vm);
|
Vector* vec = pkGetSelf(vm);
|
||||||
pkSetSlotStringFmt(vm, 0, "[%g, %g, %g]", vec->x, vec->y, vec->z);
|
pkSetSlotStringFmt(vm, 0, "[%g, %g, %g]", vec->x, vec->y, vec->z);
|
||||||
}
|
}
|
||||||
@ -291,29 +314,36 @@ DEF(_vectorRepr, "") {
|
|||||||
void registerModuleTypes(PKVM* vm) {
|
void registerModuleTypes(PKVM* vm) {
|
||||||
PkHandle* types = pkNewModule(vm, "types");
|
PkHandle* types = pkNewModule(vm, "types");
|
||||||
|
|
||||||
pkModuleAddFunction(vm, types, "hashable", _typesHashable, 1);
|
REGISTER_FN(types, "hashable", _typesHashable, 1);
|
||||||
pkModuleAddFunction(vm, types, "hash", _typesHash, 1);
|
REGISTER_FN(types, "hash", _typesHash, 1);
|
||||||
|
|
||||||
PkHandle* cls_byte_buffer = pkNewClass(vm, "ByteBuffer", NULL, types,
|
PkHandle* cls_byte_buffer = pkNewClass(vm, "ByteBuffer", NULL, types,
|
||||||
_bytebuffNew, _bytebuffDelete);
|
_bytebuffNew, _bytebuffDelete,
|
||||||
|
"A simple dynamically allocated byte buffer type. This can be used for "
|
||||||
|
"constructing larger strings without allocating and adding smaller "
|
||||||
|
"intermeidate strings.");
|
||||||
|
|
||||||
|
ADD_METHOD(cls_byte_buffer, "[]", _bytebuffSubscriptGet, 1);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "[]=", _bytebuffSubscriptSet, 2);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "reserve", _bytebuffReserve, 1);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "fill", _bytebuffFill, 2);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "clear", _bytebuffClear, 0);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "write", _bytebuffWrite, 1);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "string", _bytebuffString, 0);
|
||||||
|
ADD_METHOD(cls_byte_buffer, "count", _bytebuffCount, 0);
|
||||||
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "[]", _bytebuffSubscriptGet, 1);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "[]=", _bytebuffSubscriptSet, 2);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "reserve", _bytebuffReserve, 1);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "fill", _bytebuffFill, 2);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "clear", _bytebuffClear, 0);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "write", _bytebuffWrite, 1);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "string", _bytebuffString, 0);
|
|
||||||
pkClassAddMethod(vm, cls_byte_buffer, "count", _bytebuffCount, 0);
|
|
||||||
pkReleaseHandle(vm, cls_byte_buffer);
|
pkReleaseHandle(vm, cls_byte_buffer);
|
||||||
|
|
||||||
// TODO: add move mthods.
|
// TODO: add move mthods.
|
||||||
PkHandle* cls_vector = pkNewClass(vm, "Vector", NULL, types,
|
PkHandle* cls_vector = pkNewClass(vm, "Vector", NULL, types,
|
||||||
_vectorNew, _vectorDelete);
|
_vectorNew, _vectorDelete,
|
||||||
pkClassAddMethod(vm, cls_vector, "_init", _vectorInit, -1);
|
"A simple vector type contains x, y, and z components.");
|
||||||
pkClassAddMethod(vm, cls_vector, "@getter", _vectorGetter, 1);
|
|
||||||
pkClassAddMethod(vm, cls_vector, "@setter", _vectorSetter, 2);
|
ADD_METHOD(cls_vector, "_init", _vectorInit, -1);
|
||||||
pkClassAddMethod(vm, cls_vector, "_repr", _vectorRepr, 0);
|
ADD_METHOD(cls_vector, "@getter", _vectorGetter, 1);
|
||||||
|
ADD_METHOD(cls_vector, "@setter", _vectorSetter, 2);
|
||||||
|
ADD_METHOD(cls_vector, "_repr", _vectorRepr, 0);
|
||||||
|
|
||||||
pkReleaseHandle(vm, cls_vector);
|
pkReleaseHandle(vm, cls_vector);
|
||||||
|
|
||||||
pkRegisterModule(vm, types);
|
pkRegisterModule(vm, types);
|
||||||
|
@ -173,6 +173,17 @@ b = 'vb'; d = 'vd'; f = 'vf'
|
|||||||
assert("a ${ b + ' c ${d + " e ${f}"}' }" == "a vb c vd e vf")
|
assert("a ${ b + ' c ${d + " e ${f}"}' }" == "a vb c vd e vf")
|
||||||
assert("$b$d$f" == "vbvdvf")
|
assert("$b$d$f" == "vbvdvf")
|
||||||
|
|
||||||
|
def foo()
|
||||||
|
"a docstring to test"
|
||||||
|
end
|
||||||
|
assert(foo._docs == "a docstring to test")
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
"Testing for
|
||||||
|
class docstring"
|
||||||
|
end
|
||||||
|
assert(Foo._docs == "Testing for\n class docstring")
|
||||||
|
|
||||||
|
|
||||||
# If we got here, that means all test were passed.
|
# If we got here, that means all test were passed.
|
||||||
print('All TESTS PASSED')
|
print('All TESTS PASSED')
|
||||||
|
@ -19,9 +19,9 @@ typedef void* (*pkRealloc_t)(PKVM*, void*, size_t);
|
|||||||
typedef void (*pkReleaseHandle_t)(PKVM*, PkHandle*);
|
typedef void (*pkReleaseHandle_t)(PKVM*, PkHandle*);
|
||||||
typedef PkHandle* (*pkNewModule_t)(PKVM*, const char*);
|
typedef PkHandle* (*pkNewModule_t)(PKVM*, const char*);
|
||||||
typedef void (*pkRegisterModule_t)(PKVM*, PkHandle*);
|
typedef void (*pkRegisterModule_t)(PKVM*, PkHandle*);
|
||||||
typedef void (*pkModuleAddFunction_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int);
|
typedef void (*pkModuleAddFunction_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int, const char*);
|
||||||
typedef PkHandle* (*pkNewClass_t)(PKVM*, const char*, PkHandle*, PkHandle*, pkNewInstanceFn, pkDeleteInstanceFn);
|
typedef PkHandle* (*pkNewClass_t)(PKVM*, const char*, PkHandle*, PkHandle*, pkNewInstanceFn, pkDeleteInstanceFn, const char*);
|
||||||
typedef void (*pkClassAddMethod_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int);
|
typedef void (*pkClassAddMethod_t)(PKVM*, PkHandle*, const char*, pkNativeFn, int, const char*);
|
||||||
typedef void (*pkModuleAddSource_t)(PKVM*, PkHandle*, const char*);
|
typedef void (*pkModuleAddSource_t)(PKVM*, PkHandle*, const char*);
|
||||||
typedef PkResult (*pkRunString_t)(PKVM*, const char*);
|
typedef PkResult (*pkRunString_t)(PKVM*, const char*);
|
||||||
typedef PkResult (*pkRunFile_t)(PKVM*, const char*);
|
typedef PkResult (*pkRunFile_t)(PKVM*, const char*);
|
||||||
@ -235,16 +235,16 @@ void pkRegisterModule(PKVM* vm, PkHandle* module) {
|
|||||||
pk_api.pkRegisterModule_ptr(vm, module);
|
pk_api.pkRegisterModule_ptr(vm, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name, pkNativeFn fptr, int arity) {
|
void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name, pkNativeFn fptr, int arity, const char* docstring) {
|
||||||
pk_api.pkModuleAddFunction_ptr(vm, module, name, fptr, arity);
|
pk_api.pkModuleAddFunction_ptr(vm, module, name, fptr, arity, docstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
PkHandle* pkNewClass(PKVM* vm, const char* name, PkHandle* base_class, PkHandle* module, pkNewInstanceFn new_fn, pkDeleteInstanceFn delete_fn) {
|
PkHandle* pkNewClass(PKVM* vm, const char* name, PkHandle* base_class, PkHandle* module, pkNewInstanceFn new_fn, pkDeleteInstanceFn delete_fn, const char* docstring) {
|
||||||
return pk_api.pkNewClass_ptr(vm, name, base_class, module, new_fn, delete_fn);
|
return pk_api.pkNewClass_ptr(vm, name, base_class, module, new_fn, delete_fn, docstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkClassAddMethod(PKVM* vm, PkHandle* cls, const char* name, pkNativeFn fptr, int arity) {
|
void pkClassAddMethod(PKVM* vm, PkHandle* cls, const char* name, pkNativeFn fptr, int arity, const char* docstring) {
|
||||||
pk_api.pkClassAddMethod_ptr(vm, cls, name, fptr, arity);
|
pk_api.pkClassAddMethod_ptr(vm, cls, name, fptr, arity, docstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkModuleAddSource(PKVM* vm, PkHandle* module, const char* source) {
|
void pkModuleAddSource(PKVM* vm, PkHandle* module, const char* source) {
|
||||||
|
Loading…
Reference in New Issue
Block a user