new built-in variables for each type

This commit is contained in:
cozis
2022-08-14 13:04:53 +02:00
parent d24877c5f3
commit bc516f470a
26 changed files with 300 additions and 36 deletions
+4 -16
View File
@@ -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);
+171
View File
@@ -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");
View File
+27 -3
View File
@@ -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, },
+2 -1
View File
@@ -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[];
+1 -1
View File
@@ -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, },
+1 -1
View File
@@ -29,4 +29,4 @@
*/ */
#include "../runtime/runtime.h" #include "../runtime/runtime.h"
extern const StaticMapSlot bins_files[]; extern StaticMapSlot bins_files[];
+1 -1
View File
@@ -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 },
+1 -1
View File
@@ -29,4 +29,4 @@
*/ */
#include "../runtime/runtime.h" #include "../runtime/runtime.h"
extern const StaticMapSlot bins_math[]; extern StaticMapSlot bins_math[];
+1 -1
View File
@@ -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
View File
@@ -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)
{ {
+5
View File
@@ -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;
+5
View File
@@ -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;
+5
View File
@@ -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;
+5
View File
@@ -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;
+5
View 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);
+5
View File
@@ -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);
+5
View File
@@ -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.
+5
View File
@@ -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.
+5
View File
@@ -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;
+5
View File
@@ -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);
+5
View File
@@ -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;
+12
View File
@@ -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);
+5 -2
View File
@@ -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;
+2 -2
View File
@@ -74,7 +74,7 @@ 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;
@@ -85,7 +85,7 @@ struct StaticMapSlot {
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 {
+10
View File
@@ -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');