new built-in variables for each type
This commit is contained in:
+4
-16
@@ -9,11 +9,8 @@ fun isDigit(c)
|
|||||||
and unicode(c) >= unicode('0');
|
and unicode(c) >= unicode('0');
|
||||||
|
|
||||||
fun skip(ctx, test)
|
fun skip(ctx, test)
|
||||||
while not ended(ctx): {
|
while not ended(ctx) and test(current(ctx)):
|
||||||
if not test(current(ctx)):
|
|
||||||
break;
|
|
||||||
next(ctx);
|
next(ctx);
|
||||||
}
|
|
||||||
|
|
||||||
fun ended(ctx)
|
fun ended(ctx)
|
||||||
return ctx.i == count(ctx.str);
|
return ctx.i == count(ctx.str);
|
||||||
@@ -167,13 +164,8 @@ fun parseString(ctx) {
|
|||||||
|
|
||||||
buff = '';
|
buff = '';
|
||||||
|
|
||||||
while not ended(ctx): {
|
while not ended(ctx) and current(ctx) != '"': {
|
||||||
|
|
||||||
if current(ctx) == '"':
|
|
||||||
break;
|
|
||||||
|
|
||||||
buff = strcat(buff, current(ctx));
|
buff = strcat(buff, current(ctx));
|
||||||
|
|
||||||
next(ctx);
|
next(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,9 +183,7 @@ fun parseNumber(ctx) {
|
|||||||
# Number (int or float)
|
# Number (int or float)
|
||||||
|
|
||||||
parsed = 0;
|
parsed = 0;
|
||||||
while not ended(ctx): {
|
while not ended(ctx) and isDigit(current(ctx)): {
|
||||||
if not isDigit(current(ctx)):
|
|
||||||
break;
|
|
||||||
parsed = parsed * 10 + unicode(current(ctx)) - unicode('0');
|
parsed = parsed * 10 + unicode(current(ctx)) - unicode('0');
|
||||||
next(ctx);
|
next(ctx);
|
||||||
}
|
}
|
||||||
@@ -212,9 +202,7 @@ fun parseNumber(ctx) {
|
|||||||
return none, "Got something other than a digit after dot";
|
return none, "Got something other than a digit after dot";
|
||||||
|
|
||||||
fact = 1;
|
fact = 1;
|
||||||
while not ended(ctx): {
|
while not ended(ctx) and isDigit(current(ctx)): {
|
||||||
if not isDigit(current(ctx)):
|
|
||||||
break;
|
|
||||||
fact = fact / 10.0;
|
fact = fact / 10.0;
|
||||||
parsed = parsed + fact * (unicode(current(ctx)) - unicode('0'));
|
parsed = parsed + fact * (unicode(current(ctx)) - unicode('0'));
|
||||||
next(ctx);
|
next(ctx);
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
|
||||||
|
fun isSpace(c)
|
||||||
|
return c == " " or c == "\t" or c == "\n";
|
||||||
|
|
||||||
|
fun isDigit(c) {
|
||||||
|
u = unicode(c);
|
||||||
|
d = u - unicode("0");
|
||||||
|
return d >= 0 and d <= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun skipSpaces(context) {
|
||||||
|
# Skip zero or more whitespace characters.
|
||||||
|
while context.cur < count(context.str)
|
||||||
|
and isSpace(context.str[context.cur]):
|
||||||
|
context.cur = context.cur + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseNull(context) {
|
||||||
|
|
||||||
|
assert(context.cur < count(context)
|
||||||
|
and context.str[context.cur] == 'n');
|
||||||
|
|
||||||
|
if context.cur+3 > count(context)
|
||||||
|
or context.str[context.cur+1] != 'u'
|
||||||
|
or context.str[context.cur+2] != 'l'
|
||||||
|
or context.str[context.cur+3] != 'l':
|
||||||
|
return none, "Unexpected token starting with \"n\"";
|
||||||
|
|
||||||
|
context.cur = context.cur + count("null");
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseTrue(context) {
|
||||||
|
|
||||||
|
assert(context.cur < count(context)
|
||||||
|
and context.str[context.cur] == 't');
|
||||||
|
|
||||||
|
if context.cur+3 > count(context)
|
||||||
|
or context.str[context.cur+1] != 'r'
|
||||||
|
or context.str[context.cur+2] != 'u'
|
||||||
|
or context.str[context.cur+3] != 'e':
|
||||||
|
return none, "Unexpected token starting with \"t\"";
|
||||||
|
|
||||||
|
context.cur = context.cur + count("true");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseFalse(context) {
|
||||||
|
|
||||||
|
assert(context.cur < count(context)
|
||||||
|
and context.str[context.cur] == 'f');
|
||||||
|
|
||||||
|
if context.cur+3 > count(context)
|
||||||
|
or context.str[context.cur+1] != 'a'
|
||||||
|
or context.str[context.cur+2] != 'l'
|
||||||
|
or context.str[context.cur+3] != 's'
|
||||||
|
or context.str[context.cur+4] != 'e':
|
||||||
|
return none, "Unexpected token starting with \"f\"";
|
||||||
|
|
||||||
|
context.cur = context.cur + count("false");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun skip(context, test_callback) {
|
||||||
|
k = context.cur;
|
||||||
|
while k < count(context) and test_callback(context.str[k]):
|
||||||
|
k = k + 1;
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseInteger(context) {
|
||||||
|
assert(context.cur < count(context) and isDigit(context.str[context.cur]));
|
||||||
|
|
||||||
|
buffer = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
c = context.str[context.cur];
|
||||||
|
d = unicode(c) - unicode('0');
|
||||||
|
buffer = buffer * 10 + d;
|
||||||
|
context.cur = context.cur + 1;
|
||||||
|
} while context.cur < count(context)
|
||||||
|
and isDigit(context.str[context.cur]);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseFloating(context) {
|
||||||
|
assert(context.cur < count(context) and isDigit(context.str[context.cur]));
|
||||||
|
|
||||||
|
# It's ensured by the caller (parseIntegerOrFloating)
|
||||||
|
# that now the strings contains two sequences of
|
||||||
|
# digits with a dot in the middle.
|
||||||
|
|
||||||
|
buffer = 0.0;
|
||||||
|
|
||||||
|
# Scan the integer part.
|
||||||
|
do {
|
||||||
|
c = context.str[context.cur];
|
||||||
|
d = unicode(c) - unicode('0');
|
||||||
|
buffer = buffer * 10 + d;
|
||||||
|
context.cur = context.cur + 1;
|
||||||
|
} while context.str[context.cur] != ".";
|
||||||
|
|
||||||
|
assert(isDigit(context.str[context.cur+1]));
|
||||||
|
|
||||||
|
# Scan the decimal part.
|
||||||
|
q = 1;
|
||||||
|
do {
|
||||||
|
c = context.str[context.cur];
|
||||||
|
d = unicode(c) - unicode('0');
|
||||||
|
q = q / 10;
|
||||||
|
buffer = buffer + q * d;
|
||||||
|
context.cur = context.cur + 1;
|
||||||
|
} while context.cur < count(context)
|
||||||
|
and isDigit(context);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseIntegerOrFloating(context) {
|
||||||
|
assert(context.cur < count(context) and isDigit(context.str[context.cur]));
|
||||||
|
|
||||||
|
# Is the first digit sequence followed by a dot
|
||||||
|
# and then one or more digits?
|
||||||
|
|
||||||
|
k = skip(context, isDigit);
|
||||||
|
if k+1 < count(context) and context.str[k] == "." and isDigit(context.str[k+1]):
|
||||||
|
# It's a floating point value, then!
|
||||||
|
return parseFloating(context);
|
||||||
|
else
|
||||||
|
# It's good old integer!
|
||||||
|
return parseInteger(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseValue(context) {
|
||||||
|
|
||||||
|
if context.cur == count(context):
|
||||||
|
return none, "Source ended where a value was expected";
|
||||||
|
|
||||||
|
c = context.str[context.cur];
|
||||||
|
if c == "{":
|
||||||
|
val, err = parseObject(context);
|
||||||
|
else if c == "[":
|
||||||
|
val, err = parseArray(context);
|
||||||
|
else if c == '"':
|
||||||
|
val, err = parseString(context);
|
||||||
|
else if isDigit(c):
|
||||||
|
val, err = parseIntegerOrFloating(context);
|
||||||
|
else if c == 'n':
|
||||||
|
val, err = parseNull(context);
|
||||||
|
else if c == 't':
|
||||||
|
val, err = parseTrue(context);
|
||||||
|
else if c == 'f':
|
||||||
|
val, err = parseFalse(context);
|
||||||
|
else {
|
||||||
|
val = none;
|
||||||
|
err = strcat("Unexepected character \"", c, "\" where a value was expected");
|
||||||
|
}
|
||||||
|
return val, err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parse(str) {
|
||||||
|
context = {str: str, cur: 0};
|
||||||
|
skipSpaces(context);
|
||||||
|
val, err = parseValue(context);
|
||||||
|
return val, err;
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err = parse('3.14');
|
||||||
|
print("val=[", val, "]\n");
|
||||||
|
print("err=[", err, "]\n");
|
||||||
@@ -32,11 +32,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "math.h"
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "math.h"
|
|
||||||
#include "../utils/utf8.h"
|
#include "../utils/utf8.h"
|
||||||
|
#include "../objects/objects.h"
|
||||||
static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error)
|
static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error)
|
||||||
{
|
{
|
||||||
(void) runtime;
|
(void) runtime;
|
||||||
@@ -378,7 +378,31 @@ static int bin_bufferToString(Runtime *runtime, Object **argv, unsigned int argc
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StaticMapSlot bins_basic[] = {
|
void bins_basic_init(StaticMapSlot slots[])
|
||||||
|
{
|
||||||
|
slots[0].as_type = Object_GetTypeType();
|
||||||
|
slots[1].as_type = Object_GetNoneType();
|
||||||
|
slots[2].as_type = Object_GetIntType();
|
||||||
|
slots[3].as_type = Object_GetFloatType();
|
||||||
|
slots[4].as_type = Object_GetStringType();
|
||||||
|
slots[5].as_type = Object_GetListType();
|
||||||
|
slots[6].as_type = Object_GetMapType();
|
||||||
|
slots[7].as_type = Object_GetFileType();
|
||||||
|
slots[8].as_type = Object_GetDirType();
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticMapSlot bins_basic[] = {
|
||||||
|
|
||||||
|
{ "Type", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "None", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "int", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "float", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "String", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "List", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "Map", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "File", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
{ "Dir", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
|
||||||
|
|
||||||
{ "math", SM_SMAP, .as_smap = bins_math, },
|
{ "math", SM_SMAP, .as_smap = bins_math, },
|
||||||
// { "files", SM_SMAP, .as_smap = bins_files, },
|
// { "files", SM_SMAP, .as_smap = bins_files, },
|
||||||
// { "net", SM_SMAP, .as_smap = bins_net, },
|
// { "net", SM_SMAP, .as_smap = bins_net, },
|
||||||
|
|||||||
@@ -29,4 +29,5 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime/runtime.h"
|
||||||
extern const StaticMapSlot bins_basic[];
|
void bins_basic_init(StaticMapSlot slots[]);
|
||||||
|
extern StaticMapSlot bins_basic[];
|
||||||
@@ -296,7 +296,7 @@ static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int arg
|
|||||||
return Object_FromString(ent->d_name, -1, heap, error);
|
return Object_FromString(ent->d_name, -1, heap, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const StaticMapSlot bins_files[] = {
|
StaticMapSlot bins_files[] = {
|
||||||
{ "READ", SM_INT, .as_int = MD_READ, },
|
{ "READ", SM_INT, .as_int = MD_READ, },
|
||||||
{ "WRITE", SM_INT, .as_int = MD_WRITE, },
|
{ "WRITE", SM_INT, .as_int = MD_WRITE, },
|
||||||
{ "APPEND", SM_INT, .as_int = MD_APPEND, },
|
{ "APPEND", SM_INT, .as_int = MD_APPEND, },
|
||||||
|
|||||||
@@ -29,4 +29,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime/runtime.h"
|
||||||
extern const StaticMapSlot bins_files[];
|
extern StaticMapSlot bins_files[];
|
||||||
@@ -109,7 +109,7 @@ WRAP_FUNC(sqrt)
|
|||||||
WRAP_FUNC_2(atan2)
|
WRAP_FUNC_2(atan2)
|
||||||
WRAP_FUNC_2(pow)
|
WRAP_FUNC_2(pow)
|
||||||
|
|
||||||
const StaticMapSlot bins_math[] = {
|
StaticMapSlot bins_math[] = {
|
||||||
{ "PI", SM_FLOAT, .as_float = M_PI },
|
{ "PI", SM_FLOAT, .as_float = M_PI },
|
||||||
{ "E", SM_FLOAT, .as_float = M_E },
|
{ "E", SM_FLOAT, .as_float = M_E },
|
||||||
|
|
||||||
|
|||||||
@@ -29,4 +29,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime/runtime.h"
|
||||||
extern const StaticMapSlot bins_math[];
|
extern StaticMapSlot bins_math[];
|
||||||
@@ -504,7 +504,7 @@ static void emitInstrForExprNode(CodegenContext *ctx, ExprNode *expr,
|
|||||||
|
|
||||||
static void emitInstrForIfElseNode(CodegenContext *ctx, IfElseNode *ifelse, Label *label_break)
|
static void emitInstrForIfElseNode(CodegenContext *ctx, IfElseNode *ifelse, Label *label_break)
|
||||||
{
|
{
|
||||||
emitInstrForExprNode(ctx, ifelse->condition, label_break);
|
emitInstrForNode(ctx, ifelse->condition, label_break);
|
||||||
if(ifelse->false_branch)
|
if(ifelse->false_branch)
|
||||||
{
|
{
|
||||||
Label *label_else = Label_New(ctx);
|
Label *label_else = Label_New(ctx);
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ static _Bool interpret(Executable *exe)
|
|||||||
RuntimeError error;
|
RuntimeError error;
|
||||||
RuntimeError_Init(&error, runt); // Here we specify the runtime to snapshot in case of failure.
|
RuntimeError_Init(&error, runt); // Here we specify the runtime to snapshot in case of failure.
|
||||||
|
|
||||||
Object *bins = Object_NewStaticMap(bins_basic, runt, (Error*) &error);
|
Object *bins = Object_NewStaticMap(bins_basic, bins_basic_init, runt, (Error*) &error);
|
||||||
|
|
||||||
if(bins == NULL)
|
if(bins == NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -97,6 +97,11 @@ static _Bool to_bool(Object *obj, Error *err)
|
|||||||
return obj == &the_true_object;
|
return obj == &the_true_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeObject *Object_GetBoolType()
|
||||||
|
{
|
||||||
|
return &t_bool;
|
||||||
|
}
|
||||||
|
|
||||||
Object *Object_FromBool(_Bool val, Heap *heap, Error *error)
|
Object *Object_FromBool(_Bool val, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
(void) heap;
|
(void) heap;
|
||||||
|
|||||||
@@ -82,6 +82,11 @@ static TypeObject t_buffer_slice = {
|
|||||||
|
|
||||||
#define THRESHOLD 128
|
#define THRESHOLD 128
|
||||||
|
|
||||||
|
TypeObject *Object_GetBufferType()
|
||||||
|
{
|
||||||
|
return &t_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
_Bool Object_IsBuffer(Object *obj)
|
_Bool Object_IsBuffer(Object *obj)
|
||||||
{
|
{
|
||||||
return obj->type == &t_buffer_slice || obj->type == &t_buffer;
|
return obj->type == &t_buffer_slice || obj->type == &t_buffer;
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ static TypeObject t_dir = {
|
|||||||
.free = dir_free,
|
.free = dir_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TypeObject *Object_GetDirType()
|
||||||
|
{
|
||||||
|
return &t_dir;
|
||||||
|
}
|
||||||
|
|
||||||
_Bool Object_IsDir(Object *obj)
|
_Bool Object_IsDir(Object *obj)
|
||||||
{
|
{
|
||||||
return obj->type == &t_dir;
|
return obj->type == &t_dir;
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ static TypeObject t_file = {
|
|||||||
.free = file_free,
|
.free = file_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TypeObject *Object_GetFileType()
|
||||||
|
{
|
||||||
|
return &t_file;
|
||||||
|
}
|
||||||
|
|
||||||
_Bool Object_IsFile(Object *obj)
|
_Bool Object_IsFile(Object *obj)
|
||||||
{
|
{
|
||||||
return obj->type == &t_file;
|
return obj->type == &t_file;
|
||||||
|
|||||||
@@ -98,6 +98,11 @@ static double to_float(Object *obj, Error *err)
|
|||||||
return ((FloatObject*) obj)->val;
|
return ((FloatObject*) obj)->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeObject *Object_GetFloatType()
|
||||||
|
{
|
||||||
|
return &t_float;
|
||||||
|
}
|
||||||
|
|
||||||
Object *Object_FromFloat(double val, Heap *heap, Error *error)
|
Object *Object_FromFloat(double val, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
FloatObject *obj = (FloatObject*) Heap_Malloc(heap, &t_float, error);
|
FloatObject *obj = (FloatObject*) Heap_Malloc(heap, &t_float, error);
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ static long long int to_int(Object *obj, Error *err)
|
|||||||
return ((IntObject*) obj)->val;
|
return ((IntObject*) obj)->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeObject *Object_GetIntType()
|
||||||
|
{
|
||||||
|
return &t_int;
|
||||||
|
}
|
||||||
|
|
||||||
Object *Object_FromInt(long long int val, Heap *heap, Error *error)
|
Object *Object_FromInt(long long int val, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
assert(heap != NULL);
|
assert(heap != NULL);
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ static Object *copy(Object *self, Heap *heap, Error *err)
|
|||||||
return (Object*) ls2;
|
return (Object*) ls2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeObject *Object_GetListType()
|
||||||
|
{
|
||||||
|
return &t_list;
|
||||||
|
}
|
||||||
|
|
||||||
Object *Object_NewList(int capacity, Heap *heap, Error *error)
|
Object *Object_NewList(int capacity, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
// Handle default args.
|
// Handle default args.
|
||||||
|
|||||||
@@ -108,6 +108,11 @@ static int hash(Object *self)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeObject *Object_GetMapType()
|
||||||
|
{
|
||||||
|
return &t_map;
|
||||||
|
}
|
||||||
|
|
||||||
Object *Object_NewMap(int num, Heap *heap, Error *error)
|
Object *Object_NewMap(int num, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
// Handle default args.
|
// Handle default args.
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ static Object the_none_object = {
|
|||||||
.flags = Object_STATIC,
|
.flags = Object_STATIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TypeObject *Object_GetNoneType()
|
||||||
|
{
|
||||||
|
return &t_none;
|
||||||
|
}
|
||||||
|
|
||||||
_Bool Object_IsNone(Object *obj)
|
_Bool Object_IsNone(Object *obj)
|
||||||
{
|
{
|
||||||
return obj == &the_none_object;
|
return obj == &the_none_object;
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ static char *to_string(Object *self, int *size, Heap *heap, Error *err)
|
|||||||
return s->body;
|
return s->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeObject *Object_GetStringType()
|
||||||
|
{
|
||||||
|
return &t_string;
|
||||||
|
}
|
||||||
|
|
||||||
Object *Object_FromString(const char *str, int len, Heap *heap, Error *error)
|
Object *Object_FromString(const char *str, int len, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
assert(str != NULL);
|
assert(str != NULL);
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ TypeObject t_type = {
|
|||||||
.op_eql = op_eql,
|
.op_eql = op_eql,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TypeObject *Object_GetTypeType()
|
||||||
|
{
|
||||||
|
return &t_type;
|
||||||
|
}
|
||||||
|
|
||||||
static _Bool op_eql(Object *self, Object *other)
|
static _Bool op_eql(Object *self, Object *other)
|
||||||
{
|
{
|
||||||
return self == other;
|
return self == other;
|
||||||
|
|||||||
@@ -149,6 +149,18 @@ Object* Object_FromString(const char *str, int len, Heap *heap, Error *error);
|
|||||||
Object* Object_FromStream(FILE *fp, Heap *heap, Error *error);
|
Object* Object_FromStream(FILE *fp, Heap *heap, Error *error);
|
||||||
Object* Object_FromDIR(DIR *handle, Heap *heap, Error *error);
|
Object* Object_FromDIR(DIR *handle, Heap *heap, Error *error);
|
||||||
|
|
||||||
|
TypeObject *Object_GetTypeType();
|
||||||
|
TypeObject *Object_GetNoneType();
|
||||||
|
TypeObject *Object_GetIntType();
|
||||||
|
TypeObject *Object_GetBoolType();
|
||||||
|
TypeObject *Object_GetFloatType();
|
||||||
|
TypeObject *Object_GetStringType();
|
||||||
|
TypeObject *Object_GetListType();
|
||||||
|
TypeObject *Object_GetMapType();
|
||||||
|
TypeObject *Object_GetBufferType();
|
||||||
|
TypeObject *Object_GetFileType();
|
||||||
|
TypeObject *Object_GetDirType();
|
||||||
|
|
||||||
_Bool Object_IsNone(Object *obj);
|
_Bool Object_IsNone(Object *obj);
|
||||||
_Bool Object_IsInt(Object *obj);
|
_Bool Object_IsInt(Object *obj);
|
||||||
_Bool Object_IsBool(Object *obj);
|
_Bool Object_IsBool(Object *obj);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static int hash(Object *self)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *error)
|
Object *Object_NewStaticMap(StaticMapSlot slots[], void (*initfn)(StaticMapSlot[]), Runtime *runt, Error *error)
|
||||||
{
|
{
|
||||||
Heap *heap = Runtime_GetHeap(runt);
|
Heap *heap = Runtime_GetHeap(runt);
|
||||||
|
|
||||||
@@ -97,6 +97,9 @@ Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *er
|
|||||||
obj->slots = slots;
|
obj->slots = slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(initfn != NULL)
|
||||||
|
initfn(slots);
|
||||||
|
|
||||||
return (Object*) obj;
|
return (Object*) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +133,7 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
|||||||
case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error);
|
case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error);
|
||||||
case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error);
|
case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error);
|
||||||
case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error);
|
case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error);
|
||||||
case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error);
|
case SM_SMAP: return Object_NewStaticMap(slot.as_smap, NULL, map->runt, error);
|
||||||
case SM_NONE: return Object_NewNone(heap, error);
|
case SM_NONE: return Object_NewNone(heap, error);
|
||||||
case SM_TYPE: return (Object*) slot.as_type;
|
case SM_TYPE: return (Object*) slot.as_type;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
|
|||||||
@@ -74,18 +74,18 @@ struct StaticMapSlot {
|
|||||||
const char *name;
|
const char *name;
|
||||||
StaticMapSlotKind kind;
|
StaticMapSlotKind kind;
|
||||||
union {
|
union {
|
||||||
const StaticMapSlot *as_smap;
|
StaticMapSlot *as_smap;
|
||||||
const char *as_string;
|
const char *as_string;
|
||||||
_Bool as_bool;
|
_Bool as_bool;
|
||||||
long long int as_int;
|
long long int as_int;
|
||||||
double as_float;
|
double as_float;
|
||||||
int (*as_funct)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*);
|
int (*as_funct)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*);
|
||||||
TypeObject *as_type;
|
TypeObject *as_type;
|
||||||
};
|
};
|
||||||
union { int argc; int length; };
|
union { int argc; int length; };
|
||||||
};
|
};
|
||||||
|
|
||||||
Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *error);
|
Object *Object_NewStaticMap(StaticMapSlot slots[], void (*initfn)(StaticMapSlot[]), Runtime *runt, Error *error);
|
||||||
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *closure, Heap *heap, Error *error);
|
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *closure, Heap *heap, Error *error);
|
||||||
Object *Object_FromNativeFunction(Runtime *runtime, int (*callback)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*), int argc, Heap *heap, Error *error);
|
Object *Object_FromNativeFunction(Runtime *runtime, int (*callback)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*), int argc, Heap *heap, Error *error);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -116,4 +116,14 @@
|
|||||||
assert(r);
|
assert(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Test type variables
|
||||||
|
{
|
||||||
|
assert(type(none) == None);
|
||||||
|
assert(type(1) == int);
|
||||||
|
assert(type(10.4) == float);
|
||||||
|
assert(type("Hello, world!") == String);
|
||||||
|
assert(type([]) == List);
|
||||||
|
assert(type({}) == Map);
|
||||||
|
}
|
||||||
|
|
||||||
print('No assertion failed.\n');
|
print('No assertion failed.\n');
|
||||||
Reference in New Issue
Block a user