more comments written throught out the source

This commit is contained in:
Thakee Nathees 2021-06-03 02:14:01 +05:30
parent 2c1468f0e8
commit f9bf0c1b9c
18 changed files with 289 additions and 131 deletions

View File

@ -1,35 +1,35 @@
// To implement.
- Implement resolve path in cli.
- Implement file IO
- Implement argparse.
- -v --version
- emit opcodes
- maybe write a similer .pyc file for pocket
- --docs to generate docs from cstring.
- Ignore line with '\' character.
- Structs.
- Implement math library.
- Single header for embedding.
- --docs to generate docs from cstring.
- dump compiled code to a file.
- In keyword.
- Structs (maybe enums).
- Implement file IO (require structs).
- Implement gdb like debugger (add color print for readability).
- Implement fiber from script body and vm run fibers (not scripts).
Then remove vm's root script.
- C Integration api (including add core lib from host application).
- REPL.
- compile expression for a script.
- Var handler implement.
- Initialize imported scripts (require fiber based vm).
- REPL. compile expression for a script.
- Hex, binary literals and floats like ".5".
- Docs build to a single directory, and replace url space (%20) with a hyphen.
- Complete all the TODO; macros.
// Low priority.
- Ignore line with '\' character.
- Make it possible to override function names.
- To do so the functions and global variables should be in the same
buffer as the property of the script.
- Hex, binary literals and floats like ".5".
- Function docstring property.
- Union tagging alter in var.
- (future) add structs and maybe enums.
- Github actions.
// Add more.
- Single header for embedding (script in pk, require file IO).
[ ] Compilte core methods.
[ ] Complete var methods.
[ ] Complete core functions.

View File

@ -4,7 +4,7 @@
*/
// This file will include all source files from the cli sub-directories here
// (thirdparty/modules). into a single file. That'll make it easy to compile
// (thirdparty/modules) into a single file. That'll make it easy to compile
// with the command `gcc cli/*.c ...` instead of adding each sub-directory to
// the list of source directory.

View File

@ -18,7 +18,7 @@ ROOT_URL = 'https://thakeenathees.github.io/pocketlang/'
## Home page should be in the SOURCE_DIR.
HOME_PAGE = 'home.md'
TRY_PAGE = 'try it now.html'
TRY_PAGE = 'try-it-now.html'
SOURCE_DIR = 'pages/'
TARGET_DIR = 'build/'
STATIC_DIR = 'static/'
@ -36,14 +36,16 @@ WASM_SOURCE_FILES = '''\
'''
## Navigation pages in order. Should match the path names.
## Any file/folder name shouldn't contain white space.
PAGES = [
('Getting Started', [
('Getting-Started', [
TRY_PAGE,
'build from source.md',
'learn-in-5-minutes.md',
'build-from-source.md',
'contributing.md',
]),
('Language API', [
('Language-API', [
'variables.md',
'functions.md',
'modules.md',
@ -85,15 +87,17 @@ def main():
ctx = generate_page_context(join(SOURCE_DIR, HOME_PAGE), index_html, navigation)
write_page(ctx, template, index_html)
for entry in PAGES:
for entry in PAGES: ## entry = ('dirname', [files...])
_dir = entry[0]
for file in entry[1]:
ext = get_validated_ext(file)
path = join(SOURCE_DIR, _dir, file)
dst = ''
if ext == '.md' : dst = join(TARGET_DIR, _dir, file.replace('.md', '.html'))
else: dst = join(TARGET_DIR, _dir, file)
dst = ''; path_prefix = _dir.lower().replace(' ', '-') + '-'
if ext == '.md':
dst = join(TARGET_DIR, path_prefix + file.replace('.md', '.html'))
else:
dst = join(TARGET_DIR, path_prefix + file)
ctx = generate_page_context(path, dst, navigation)
_template = template
@ -108,22 +112,27 @@ def generate_navigation():
for entry in PAGES:
_dir = entry[0]
navigation += '<div class="navigation">\n'
navigation += '<h3><strong>%s</strong></h3>\n' % (_dir)
navigation += '<h3><strong>%s</strong></h3>\n' % (_dir.replace('-', ' ').title())
navigation += '<ul class="menu">\n'
for file in entry[1]:
ext = get_validated_ext(file)
link = '' ## Assuming that file name don't contain '.md' at the middle.
if ext == '.md': link = join(ROOT_URL, _dir, file.replace('.md', '.html'))
else: link = join(ROOT_URL, _dir, file)
path_prefix = _dir.lower().replace(' ', '-') + '-'
if ext == '.md':
link = join(ROOT_URL, path_prefix + file.replace('.md', '.html'))
else:
link = join(ROOT_URL, path_prefix + file)
link = link.replace('\\', '/')
title = file.replace(ext, '')
title = file.replace(ext, '').replace('-', ' ').title()
navigation += '<li><a href="%s">%s</a></li>\n' % (link, title)
navigation += '</ul>\n'
navigation += '</div>\n'
return navigation
@ -155,6 +164,9 @@ def path_to_title(path):
## Return the static dir relative path.
def relative_static_dir(dst):
return STATIC_DIR ## No more relative paths.
_dir = os.path.dirname(dst)
static_dir = os.path.relpath(join(TARGET_DIR, STATIC_DIR), _dir)
static_dir = static_dir.replace('\\', '/')
@ -203,8 +215,7 @@ def custom_html_override(src, content):
'<span class="n">%s</span>' % nk)
## codehilite mark the compilation command as error.
if 'build from source' in src:
content = content.replace('<span class="err">', '<span>')
content = content.replace('<span class="err">', '<span>')
return content
@ -227,9 +238,11 @@ if __name__ == '__main__':
_local = False
if len(sys.argv) >= 2:
if sys.argv[1] == 'local':
ROOT_URL = 'http://localhost:8000/'
_local = True
#ROOT_URL = 'http://localhost:8000/'
ROOT_URL = '' ## No more nested directory pages.
main()
## Write a batch file to start the server in windows.

View File

@ -0,0 +1,83 @@
# Learn pocketlang in 5 minutes
```ruby
# This is a comment.
x = 0 # Creating a variable.
# The value '0' is a type of number.
# In pocketlang statements should end with a new line
# or a semicollon. White space characters except for new
# lines are ignored in pocketlang.
a = 1; b = 2;
# Data types.
# -----------
# Primitive types
null # A null type.
true; false # Booleans.
42; 3.14 # Numbers.
0..10; 10..0 # Range (0..10 = 0 <= r < 10).
# Object types
"hello"; 'world' # Strings (support multiline).
[42, 'foo', null] # Lists.
{ 'Key':'value' } # Maps.
func(x) return x*x end # Lambda/literal functions.
import lang # Module (imported scripts).
# Control flow.
# -------------
# If condition.
if x == 'foo'
print('bar')
elif x == 'bar'
print('baz')
end
# In a single line (should add 'then' keyword).
if x == 'foo' then print('bar') end
# For loops, here 'do' keyword is optional if we have a
# newline after the sequence (like 'then' in if statements).
for i in 0..10 do
print(i)
end
# While statement.
while x > 0 do print(x -= 1) end
# In pocketlang variable's lifetime are scope based.
if true then
local = null
end
#print(local) # Error: Name 'local' is not defined.
# Functions.
#-----------
def add(a, b)
return a + b
end
# Functions can be assigned to a variable.
fn = func(x) return x*x end
# Functions can be passed as an argument and can be returned.
def call(fn, x)
fn(x)
return func print('foo') end
end
# Concanative call operator '->'
str_lower(str_strip('FOO ')) # This can be written as below
'FOO ' -> str_strip -> str_lower
'foo' -> print # similer as print('foo')
```

View File

@ -365,6 +365,7 @@ static OpInfo opcode_info[] = {
* ERROR HANDLERS *
*****************************************************************************/
// Internal error report function of the parseError() function.
static void reportError(Compiler* compiler, const char* file, int line,
const char* fmt, va_list args) {
PKVM* vm = compiler->vm;

View File

@ -17,16 +17,22 @@
/* PUBLIC API */
/*****************************************************************************/
// Declare internal functions of public api.
// Create a new module with the given [name] and returns as a Script* for
// internal. Which will be wrapped by pkNewModule to return a pkHandle*.
static Script* newModuleInternal(PKVM* vm, const char* name);
static void moduleAddFunctionInternal(PKVM* vm, Script* script,
const char* name, pkNativeFn fptr, int arity);
// The internal function to add functions to a module.
static void moduleAddFunctionInternal(PKVM* vm, Script* script,
const char* name, pkNativeFn fptr,
int arity);
// pkNewModule implementation (see pocketlang.h for description).
PkHandle* pkNewModule(PKVM* vm, const char* name) {
Script* module = newModuleInternal(vm, name);
return vmNewHandle(vm, VAR_OBJ(&module->_super));
}
// pkModuleAddFunction implementation (see pocketlang.h for description).
void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name,
pkNativeFn fptr, int arity) {
__ASSERT(module != NULL, "Argument module was NULL.");
@ -38,18 +44,18 @@ void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name,
moduleAddFunctionInternal(vm, (Script*)AS_OBJ(scr), name, fptr, arity);
}
// Argument getter (1 based).
// A convinent macro to get the nth (1 based) argument of the current function.
#define ARG(n) vm->fiber->ret[n]
// Convinent macros.
// Convinent macros to get the 1st, 2nd, 3rd arguments.
#define ARG1 ARG(1)
#define ARG2 ARG(2)
#define ARG3 ARG(3)
// Argument count used in variadic functions.
// Evaluvates to the current function's argument count.
#define ARGC ((int)(vm->fiber->sp - vm->fiber->ret) - 1)
// Set return value and return.
// Set return value for the current native function and return.
#define RET(value) \
do { \
*(vm->fiber->ret) = value; \
@ -63,6 +69,7 @@ void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name,
__ASSERT(value != NULL, "Parameter [value] was NULL."); \
((void*)0)
// Set error for incompatible type provided as an argument.
#define ERR_INVALID_ARG_TYPE(m_type) \
do { \
char buff[STR_INT_BUFF_SIZE]; \
@ -71,11 +78,13 @@ do { \
" at argument $.", buff); \
} while (false)
// pkGetArgc implementation (see pocketlang.h for description).
int pkGetArgc(PKVM* vm) {
__ASSERT(vm->fiber != NULL, "This function can only be called at runtime.");
return ARGC;
}
// pkGetArg implementation (see pocketlang.h for description).
PkVar pkGetArg(PKVM* vm, int arg) {
__ASSERT(vm->fiber != NULL, "This function can only be called at runtime.");
__ASSERT(arg > 0 || arg <= ARGC, "Invalid argument index.");
@ -83,6 +92,7 @@ PkVar pkGetArg(PKVM* vm, int arg) {
return &(ARG(arg));
}
// pkGetArgBool implementation (see pocketlang.h for description).
bool pkGetArgBool(PKVM* vm, int arg, bool* value) {
CHECK_GET_ARG_API_ERRORS();
@ -91,6 +101,7 @@ bool pkGetArgBool(PKVM* vm, int arg, bool* value) {
return true;
}
// pkGetArgNumber implementation (see pocketlang.h for description).
bool pkGetArgNumber(PKVM* vm, int arg, double* value) {
CHECK_GET_ARG_API_ERRORS();
@ -109,6 +120,7 @@ bool pkGetArgNumber(PKVM* vm, int arg, double* value) {
return true;
}
// pkGetArgString implementation (see pocketlang.h for description).
bool pkGetArgString(PKVM* vm, int arg, const char** value) {
CHECK_GET_ARG_API_ERRORS();
@ -124,6 +136,7 @@ bool pkGetArgString(PKVM* vm, int arg, const char** value) {
return true;
}
// pkGetArgValue implementation (see pocketlang.h for description).
bool pkGetArgValue(PKVM* vm, int arg, PkVarType type, PkVar* value) {
CHECK_GET_ARG_API_ERRORS();
@ -139,54 +152,36 @@ bool pkGetArgValue(PKVM* vm, int arg, PkVarType type, PkVar* value) {
return true;
}
// pkReturnNull implementation (see pocketlang.h for description).
void pkReturnNull(PKVM* vm) {
RET(VAR_NULL);
}
// pkReturnBool implementation (see pocketlang.h for description).
void pkReturnBool(PKVM* vm, bool value) {
RET(VAR_BOOL(value));
}
// pkReturnNumber implementation (see pocketlang.h for description).
void pkReturnNumber(PKVM* vm, double value) {
RET(VAR_NUM(value));
}
// pkReturnString implementation (see pocketlang.h for description).
void pkReturnString(PKVM* vm, const char* value) {
RET(VAR_OBJ(&newString(vm, value)->_super));
}
// pkReturnStringLength implementation (see pocketlang.h for description).
void pkReturnStringLength(PKVM* vm, const char* value, size_t length) {
RET(VAR_OBJ(&newStringLength(vm, value, (uint32_t)length)->_super));
}
// pkReturnValue implementation (see pocketlang.h for description).
void pkReturnValue(PKVM* vm, PkVar value) {
RET(*(Var*)value);
}
/*****************************************************************************/
/* CORE INTERNAL */
/*****************************************************************************/
static void initializeBuiltinFN(PKVM* vm, BuiltinFn* bfn, const char* name,
int length, int arity, pkNativeFn ptr) {
bfn->name = name;
bfn->length = length;
bfn->fn = newFunction(vm, name, length, NULL, true);
bfn->fn->arity = arity;
bfn->fn->native = ptr;
}
int findBuiltinFunction(PKVM* vm, const char* name, uint32_t length) {
for (int i = 0; i < vm->builtins_count; i++) {
if (length == vm->builtins[i].length &&
strncmp(name, vm->builtins[i].name, length) == 0) {
return i;
}
}
return -1;
}
/*****************************************************************************/
/* VALIDATORS */
/*****************************************************************************/
@ -259,16 +254,30 @@ static inline bool validateIndex(PKVM* vm, int32_t index, int32_t size,
/* BUILTIN FUNCTIONS API */
/*****************************************************************************/
// findBuiltinFunction implementation (see core.h for description).
int findBuiltinFunction(PKVM* vm, const char* name, uint32_t length) {
for (int i = 0; i < vm->builtins_count; i++) {
if (length == vm->builtins[i].length &&
strncmp(name, vm->builtins[i].name, length) == 0) {
return i;
}
}
return -1;
}
// getBuiltinFunction implementation (see core.h for description).
Function* getBuiltinFunction(PKVM* vm, int index) {
ASSERT_INDEX(index, vm->builtins_count);
return vm->builtins[index].fn;
}
// getBuiltinFunctionName implementation (see core.h for description).
const char* getBuiltinFunctionName(PKVM* vm, int index) {
ASSERT_INDEX(index, vm->builtins_count);
return vm->builtins[index].name;
}
// getCoreLib implementation (see core.h for description).
Script* getCoreLib(PKVM* vm, String* name) {
Var lib = mapGet(vm->core_libs, VAR_OBJ(&name->_super));
if (IS_UNDEF(lib)) return NULL;
@ -309,16 +318,14 @@ FN_IS_OBJ_TYPE(UserObj, OBJ_USER)
PK_DOC(coreTypeName,
"type_name(value:var) -> string\n"
"Returns the type name of the of the value.");
void coreTypeName(PKVM* vm) {
"Returns the type name of the of the value.") {
RET(VAR_OBJ(&newString(vm, varTypeName(ARG1))->_super));
}
PK_DOC(coreAssert,
"assert(condition:bool [, msg:string]) -> void\n"
"If the condition is false it'll terminate the current fiber with the "
"optional error message");
void coreAssert(PKVM* vm) {
"optional error message") {
int argc = ARGC;
if (argc != 1 && argc != 2) {
vm->fiber->error = newString(vm, "Invalid argument count.");
@ -345,16 +352,14 @@ void coreAssert(PKVM* vm) {
PK_DOC(coreToString,
"to_string(value:var) -> string\n"
"Returns the string representation of the value.");
void coreToString(PKVM* vm) {
"Returns the string representation of the value.") {
RET(VAR_OBJ(&toString(vm, ARG1)->_super));
}
PK_DOC(corePrint,
"print(...) -> void\n"
"Write each argument as comma seperated to the stdout and ends with a "
"newline.");
void corePrint(PKVM* vm) {
"newline.") {
// If the host appliaction donesn't provide any write function, discard the
// output.
if (vm->config.write_fn == NULL) return;
@ -379,8 +384,9 @@ void corePrint(PKVM* vm) {
// String functions.
// -----------------
void coreStrLower(PKVM* vm) {
PK_DOC(coreStrLower,
"str_lower(value:string) -> string\n"
"Returns a lower-case version of the given string.") {
String* str;
if (!validateArgString(vm, 1, &str)) return;
@ -393,7 +399,9 @@ void coreStrLower(PKVM* vm) {
RET(VAR_OBJ(&result->_super));
}
void coreStrUpper(PKVM* vm) {
PK_DOC(coreStrUpper,
"str_upper(value:string) -> string\n"
"Returns a upper-case version of the given string.") {
String* str;
if (!validateArgString(vm, 1, &str)) return;
@ -406,7 +414,10 @@ void coreStrUpper(PKVM* vm) {
RET(VAR_OBJ(&result->_super));
}
void coreStrStrip(PKVM* vm) {
PK_DOC(coreStrStrip,
"str_strip(value:string) -> string\n"
"Returns a copy of the string as the leading and trailing white spaces are"
"trimed.") {
String* str;
if (!validateArgString(vm, 1, &str)) return;
@ -420,19 +431,21 @@ void coreStrStrip(PKVM* vm) {
RET(VAR_OBJ(&newStringLength(vm, start, (uint32_t)(end - start + 1))->_super));
}
// Returns the ASCII string value of the integer argument.
void coreStrChr(PKVM* vm) {
PK_DOC(coreStrChr,
"str_chr(value:number) -> string\n"
"Returns the ASCII string value of the integer argument.") {
int32_t num;
if (!validateInteger(vm, ARG1, &num, "Argument 1"));
if (!validateInteger(vm, ARG1, &num, "Argument 1")) return;
char c = (char)num;
RET(VAR_OBJ(&newStringLength(vm, &c, 1)->_super));
}
// Returns integer value of the given ASCII character.
void coreStrOrd(PKVM* vm) {
PK_DOC(coreStrOrd,
"str_ord(value:string) -> number\n"
"Returns integer value of the given ASCII character.") {
String* c;
if (!validateArgString(vm, 1, &c));
if (!validateArgString(vm, 1, &c)) return;
if (c->length != 1) {
vm->fiber->error = newString(vm, "Expected a string of length 1.");
RET(VAR_NULL);
@ -442,10 +455,12 @@ void coreStrOrd(PKVM* vm) {
}
// List functions.
// ---------------
void coreListAppend(PKVM* vm) {
PK_DOC(coreListAppend,
"list_append(self:List, value:var) -> List\n"
"Append the [value] to the list [self] and return the list.") {
List* list;
if (!validateArgList(vm, 1, &list)) return;
Var elem = ARG(2);
@ -457,13 +472,15 @@ void coreListAppend(PKVM* vm) {
// Map functions.
// --------------
void coreMapRemove(PKVM* vm) {
PK_DOC(coreMapRemove,
"map_remove(self:map, key:var) -> var\n"
"Remove the [key] from the map [self] and return it's value if the key "
"exists, otherwise it'll return null.") {
Map* map;
if (!validateArgMap(vm, 1, &map)) return;
Var key = ARG(2);
mapRemoveKey(vm, map, key);
RET(VAR_OBJ(&map->_super));
RET(mapRemoveKey(vm, map, key));
}
/*****************************************************************************/
@ -497,8 +514,10 @@ static Script* newModuleInternal(PKVM* vm, const char* name) {
return scr;
}
// An internal function to add a function to the given [script].
static void moduleAddFunctionInternal(PKVM* vm, Script* script,
const char* name, pkNativeFn fptr, int arity) {
const char* name, pkNativeFn fptr,
int arity) {
// Check if function with the same name already exists.
if (scriptSearchFunc(script, name, (uint32_t)strlen(name)) != -1) {
@ -624,6 +643,17 @@ void stdMathHash(PKVM* vm) {
/*****************************************************************************/
/* CORE INITIALIZATION */
/*****************************************************************************/
static void initializeBuiltinFN(PKVM* vm, BuiltinFn* bfn, const char* name,
int length, int arity, pkNativeFn ptr) {
bfn->name = name;
bfn->length = length;
bfn->fn = newFunction(vm, name, length, NULL, true);
bfn->fn->arity = arity;
bfn->fn->native = ptr;
}
void initializeCore(PKVM* vm) {
#define INITALIZE_BUILTIN_FN(name, fn, argc) \
@ -817,6 +847,7 @@ bool varLesser(Var v1, Var v2) {
#define IS_ATTRIB(name) \
(attrib->length == strlen(name) && strcmp(name, attrib->data) == 0)
// Set error for accessing non-existed attribute.
#define ERR_NO_ATTRIB() \
vm->fiber->error = stringFormat(vm, "'$' objects has no attribute " \
"named '$'", \

View File

@ -30,19 +30,25 @@ Script* getCoreLib(PKVM* vm, String* name);
/* OPERATORS */
/*****************************************************************************/
Var varAdd(PKVM* vm, Var v1, Var v2);
Var varSubtract(PKVM* vm, Var v1, Var v2);
Var varMultiply(PKVM* vm, Var v1, Var v2);
Var varDivide(PKVM* vm, Var v1, Var v2);
Var varModulo(PKVM* vm, Var v1, Var v2);
Var varAdd(PKVM* vm, Var v1, Var v2); // Returns v1 + v2.
Var varSubtract(PKVM* vm, Var v1, Var v2); // Returns v1 - v2.
Var varMultiply(PKVM* vm, Var v1, Var v2); // Returns v1 * v2.
Var varDivide(PKVM* vm, Var v1, Var v2); // Returns v1 / v2.
Var varModulo(PKVM* vm, Var v1, Var v2); // Returns v1 % v2.
bool varGreater(Var v1, Var v2);
bool varLesser(Var v1, Var v2);
bool varGreater(Var v1, Var v2); // Returns v1 > v2.
bool varLesser(Var v1, Var v2); // Returns v1 < v2.
// Returns the attribute named [attrib] on the variable [on].
Var varGetAttrib(PKVM* vm, Var on, String* attrib);
// Set the attribute named [attrib] on the variable [on] with the given [value].
void varSetAttrib(PKVM* vm, Var on, String* name, Var value);
// Returns the subscript value (ie. on[key]).
Var varGetSubscript(PKVM* vm, Var on, Var key);
// Set subscript [value] with the [key] (ie. on[key] = value).
void varsetSubscript(PKVM* vm, Var on, Var key, Var value);
#endif // CORE_H

View File

@ -57,10 +57,13 @@ extern "C" {
// A convinent macro to define documentation of funcions. Use it to document
// your native functions.
//
// PK_DOC(foo, "The function will print 'foo' on the console.");
// void foo(PKVM* vm) { printf("foo\n"); }
// PK_DOC(foo,
// "The function will print 'foo' on the console.") {
// printf("foo\n");
// }
//
#define PK_DOC(func, doc) static char __pkdoc__##func[] = doc
#define PK_DOC(func, doc) \
static char __pkdoc__##func[] = doc; void func(PKVM* vm)
/*****************************************************************************/
/* POCKETLANG TYPES */

View File

@ -5,6 +5,7 @@
#include "utils.h"
// Function implementation, see utils.h for description.
int utilPowerOf2Ceil(int n) {
n--;
n |= n >> 1;
@ -17,10 +18,12 @@ int utilPowerOf2Ceil(int n) {
return n;
}
// Function implementation, see utils.h for description.
bool utilIsName(char c) {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_');
}
// Function implementation, see utils.h for description.
bool utilIsDigit(char c) {
return ('0' <= c && c <= '9');
}
@ -32,18 +35,21 @@ typedef union {
double num;
} _DoubleBitsConv;
// Function implementation, see utils.h for description.
uint64_t utilDoubleToBits(double value) {
_DoubleBitsConv bits;
bits.num = value;
return bits.bits64;
}
// Function implementation, see utils.h for description.
double utilDoubleFromBits(uint64_t value) {
_DoubleBitsConv bits;
bits.bits64 = value;
return bits.num;
}
// Function implementation, see utils.h for description.
uint32_t utilHashBits(uint64_t hash) {
// From v8's ComputeLongHash() which in turn cites:
// Thomas Wang, Integer Hash Functions.
@ -57,11 +63,13 @@ uint32_t utilHashBits(uint64_t hash) {
return (uint32_t)(hash & 0x3fffffff);
}
// Function implementation, see utils.h for description.
uint32_t utilHashNumber(double num) {
// Hash the raw bits of the value.
return utilHashBits(utilDoubleToBits(num));
}
// Function implementation, see utils.h for description.
uint32_t utilHashString(const char* string) {
// FNV-1a hash. See: http://www.isthe.com/chongo/tech/comp/fnv/
@ -85,6 +93,7 @@ uint32_t utilHashString(const char* string) {
* UTF8 *
****************************************************************************/
// Function implementation, see utils.h for description.
int utf8_encodeBytesCount(int value) {
if (value <= 0x7f) return 1;
if (value <= 0x7ff) return 2;
@ -95,6 +104,7 @@ int utf8_encodeBytesCount(int value) {
return 0;
}
// Function implementation, see utils.h for description.
int utf8_decodeBytesCount(uint8_t byte) {
if ((byte >> 7) == 0b0) return 1;
@ -107,6 +117,7 @@ int utf8_decodeBytesCount(uint8_t byte) {
return 1;
}
// Function implementation, see utils.h for description.
int utf8_encodeValue(int value, uint8_t* bytes) {
if (value <= 0x7f) {
@ -145,6 +156,7 @@ int utf8_encodeValue(int value, uint8_t* bytes) {
return 0;
}
// Function implementation, see utils.h for description.
int utf8_decodeBytes(uint8_t* bytes, int* value) {
int continue_bytes = 0;

View File

@ -32,6 +32,7 @@ PkVarType pkGetValueType(PkVar value) {
case OBJ_SCRIPT: return PK_SCRIPT;
case OBJ_FUNC: return PK_FUNCTION;
case OBJ_FIBER: return PK_FIBER;
case OBJ_USER: TODO; break;
}
UNREACHABLE();

View File

@ -23,16 +23,13 @@ triangle = ">++++[<++++++++>-]>++++++++[>++++<-]>>++>>>+>>>+<<<<<<<<<<[-[->+<]>
[-]<]+++++"
## Source: https://github.com/fabianishere/brainfuck/blob/master/examples/math/fib.bf
fibonacci = ">++++++++++>+>+[
[+++++[>++++++++<-]>.<++++++[>--------<-]+<<<]>.>>[
[-]<[>+<-]>>[<<+>+>-]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-
[>+<-[>+<-[>+<-[>[-]>+>+<<<-[>+<-]]]]]]]]]]]+>>>
]<<<
]"
fibonacci = ">++++++++++>+>+[[+++++[>++++++++<-]>.<++++++[>--------<-]+<<<]>.
>>[[-]<[>+<-]>>[<<+>+>-]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+
<-[>+<-[>[-]>+>+<<<-[>+<-]]]]]]]]]]]+>>>]<<<]"
execute(hello_world)
execute(triangle)
execute(fibonacci)
##execute(fibonacci) This will run endlessly (cannot run test).
###############################################################################
## INTERNAL ##

View File

@ -2,17 +2,22 @@ import subprocess, os, sys
import json, re
from os.path import join
FMT_PATH = "%-25s"
INDENTATION = ' | '
## All the test files.
test_files = [
"lang/basics.pk",
"lang/functions.pk",
"lang/controlflow.pk",
"lang/import.pk",
"examples/helloworld.pk",
"examples/brainfuck.pk",
"examples/fib.pk",
"examples/prime.pk",
"examples/fizzbuzz.pk",
"examples/pi.pk",
]
## All benchmark files. ## TODO: pass args for iterations.
benchmarks = {
"factors" : ['.pk', '.py', '.rb', '.wren'],
"fib" : ['.pk', '.py', '.rb', '.wren'],
@ -21,10 +26,14 @@ benchmarks = {
"primes" : ['.pk', '.py', '.rb', ".wren"],
}
def main():
run_all_tests()
run_all_benchmarks()
def run_all_benchmarks():
print("--------------------------------")
print(" BENCHMARKS ")
print("--------------------------------")
print_title("BENCHMARKS")
def get_interpreter(file):
if file.endswith('.pk' ) : return 'pocket'
@ -47,23 +56,21 @@ def run_all_benchmarks():
print('%10ss'%time[0])
def run_all_tests():
print("--------------------------------")
print(" TESTS ")
print("--------------------------------")
for path in test_files:
run_file(path)
print_title("TESTS")
def run_file(path):
print(FMT_PATH % path, end='')
result = run_command(['pocket', path])
if result.returncode != 0:
print('-- Failed')
err = INDENTATION + result.stderr \
.decode('utf8') \
.replace('\n', '\n' + INDENTATION)
print(err)
else:
print('-- OK')
FMT_PATH = "%-25s"
INDENTATION = ' | '
for path in test_files:
print(FMT_PATH % path, end='')
result = run_command(['pocket', path])
if result.returncode != 0:
print('-- Failed')
err = INDENTATION + result.stderr \
.decode('utf8') \
.replace('\n', '\n' + INDENTATION)
print(err)
else:
print('-- OK')
def run_command(command):
@ -71,6 +78,10 @@ def run_command(command):
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
run_all_tests()
run_all_benchmarks()
def print_title(title):
print("--------------------------------")
print(" %s " % title)
print("--------------------------------")
if __name__ == '__main__':
main()