pocketlang/src/var.c

159 lines
3.4 KiB
C
Raw Normal View History

2021-02-07 15:40:00 +08:00
/*
* Copyright (c) 2020-2021 Thakee Nathees
* Licensed under: MIT License
*/
#include "var.h"
#include "vm.h"
2021-02-12 01:35:43 +08:00
// Number of maximum digits for to_string buffer.
#define TO_STRING_BUFF_SIZE 128
2021-02-08 02:30:29 +08:00
void varInitObject(Object* self, MSVM* vm, ObjectType type) {
2021-02-12 01:35:43 +08:00
self->type = type;
self->next = vm->first;
vm->first = self;
// TODO: set isGray = false;
2021-02-07 15:40:00 +08:00
}
#if VAR_NAN_TAGGING
// A union to reinterpret a double as raw bits and back.
typedef union {
2021-02-12 01:35:43 +08:00
uint64_t bits64;
uint32_t bits32[2];
double num;
2021-02-07 15:40:00 +08:00
} _DoubleBitsConv;
#endif
Var doubleToVar(double value) {
#if VAR_NAN_TAGGING
2021-02-12 01:35:43 +08:00
_DoubleBitsConv bits;
bits.num = value;
return bits.bits64;
2021-02-07 15:40:00 +08:00
#else
2021-02-12 01:35:43 +08:00
// TODO:
2021-02-07 15:40:00 +08:00
#endif // VAR_NAN_TAGGING
}
2021-02-11 01:23:48 +08:00
double varToDouble(Var value) {
2021-02-07 15:40:00 +08:00
#if VAR_NAN_TAGGING
2021-02-12 01:35:43 +08:00
_DoubleBitsConv bits;
bits.bits64 = value;
return bits.num;
2021-02-07 15:40:00 +08:00
#else
2021-02-12 01:35:43 +08:00
// TODO:
2021-02-07 15:40:00 +08:00
#endif // VAR_NAN_TAGGING
}
2021-02-08 02:30:29 +08:00
String* newString(MSVM* vm, const char* text, uint32_t length) {
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
ASSERT(length == 0 || text != NULL, "Unexpected NULL string.");
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
String* string = ALLOCATE_DYNAMIC(vm, String, length + 1, char);
varInitObject(&string->_super, vm, OBJ_STRING);
string->length = length;
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
if (length != 0) memcpy(string->data, text, length);
string->data[length] = '\0';
return string;
2021-02-07 15:40:00 +08:00
}
2021-02-08 02:30:29 +08:00
Script* newScript(MSVM* vm) {
2021-02-12 01:35:43 +08:00
Script* script = ALLOCATE(vm, Script);
varInitObject(&script->_super, vm, OBJ_SCRIPT);
varBufferInit(&script->globals);
nameTableInit(&script->global_names);
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
varBufferInit(&script->literals);
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
vmPushTempRef(vm, &script->_super);
script->body = newFunction(vm, "@(ScriptLevel)", script, false);
vmPopTempRef(vm);
2021-02-09 16:21:10 +08:00
2021-02-12 01:35:43 +08:00
functionBufferInit(&script->functions);
nameTableInit(&script->function_names);
2021-02-09 16:21:10 +08:00
2021-02-12 01:35:43 +08:00
stringBufferInit(&script->names);
2021-02-11 01:23:48 +08:00
2021-02-12 01:35:43 +08:00
return script;
2021-02-07 15:40:00 +08:00
}
2021-02-08 02:30:29 +08:00
Function* newFunction(MSVM* vm, const char* name, Script* owner,
2021-02-07 15:40:00 +08:00
bool is_native) {
2021-02-12 01:35:43 +08:00
Function* func = ALLOCATE(vm, Function);
varInitObject(&func->_super, vm, OBJ_FUNC);
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
func->name = name;
func->owner = owner;
func->arity = -1;
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
func->is_native = is_native;
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
if (is_native) {
func->native = NULL;
} else {
vmPushTempRef(vm, &func->_super);
Fn* fn = ALLOCATE(vm, Fn);
vmPopTempRef(vm);
2021-02-07 15:40:00 +08:00
2021-02-12 01:35:43 +08:00
byteBufferInit(&fn->opcodes);
intBufferInit(&fn->oplines);
fn->stack_size = 0;
func->fn = fn;
}
return func;
2021-02-07 15:40:00 +08:00
}
2021-02-09 16:21:10 +08:00
2021-02-11 01:23:48 +08:00
// Utility functions //////////////////////////////////////////////////////////
2021-02-09 16:21:10 +08:00
bool isVauesSame(Var v1, Var v2) {
#if VAR_NAN_TAGGING
2021-02-12 01:35:43 +08:00
// Bit representation of each values are unique so just compare the bits.
return v1 == v2;
2021-02-09 16:21:10 +08:00
#else
#error TODO:
#endif
2021-02-11 01:23:48 +08:00
}
2021-02-12 01:35:43 +08:00
String* toString(MSVM* vm, Var v) {
if (IS_NULL(v)) {
return newString(vm, "null", 4);
} else if (IS_BOOL(v)) {
if (AS_BOOL(v)) {
return newString(vm, "true", 4);
} else {
return newString(vm, "false", 5);
}
} else if (IS_NUM(v)) {
char buff[TO_STRING_BUFF_SIZE];
int length = sprintf(buff, "%.14g", AS_NUM(v));
ASSERT(length < TO_STRING_BUFF_SIZE, "Buffer overflowed.");
return newString(vm, buff, length);
} else if (IS_OBJ(v)) {
Object* obj = AS_OBJ(v);
switch (obj->type) {
case OBJ_STRING:
return newString(vm, ((String*)obj)->data, ((String*)obj)->length);
break;
case OBJ_ARRAY: TODO;
case OBJ_MAP: TODO;
case OBJ_RANGE: TODO;
case OBJ_SCRIPT: TODO;
case OBJ_FUNC: TODO;
case OBJ_INSTANCE: TODO;
case OBJ_USER: TODO;
break;
}
}
UNREACHABLE();
return NULL;
}