MBED port of https://github.com/ys1382/filagree . The only change is adding #define MBED

Dependents:   filagree_test

Revision:
0:1a89e28dea91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/variable.c	Wed May 30 21:13:01 2012 +0000
@@ -0,0 +1,334 @@
+#include <string.h>
+/*#include <stdio.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <time.h>
+#include "util.h"
+#include "sys.h"
+*/
+#include "vm.h"
+#include "struct.h"
+#include "serial.h"
+#include "variable.h"
+#include "util.h"
+
+#define    ERROR_VAR_TYPE    "type error"
+#define VAR_MAX    100
+
+const struct number_string var_types[] = {
+    {VAR_NIL,        "nil"},
+    {VAR_INT,        "integer"},
+    {VAR_BOOL,        "boolean"},
+    {VAR_FLT,        "float"},
+    {VAR_STR,        "string"},
+    {VAR_LST,        "list"},
+    {VAR_FNC,        "function"},
+    {VAR_MAP,        "map"},
+    {VAR_ERR,        "error"},
+    {VAR_C,            "c-function"},
+};
+
+const char *var_type_str(enum VarType vt)
+{
+    return NUM_TO_STRING(var_types, vt);
+}
+
+struct variable* variable_new(struct Context *context, enum VarType type)
+{
+	null_check(context);
+   if (context->num_vars++ > VAR_MAX)
+        garbage_collect(context);
+    struct variable* v = (struct variable*)malloc(sizeof(struct variable));
+    v->type = type;
+    v->map = NULL;
+    v->marked = false;
+    return v;
+}
+
+struct variable* variable_new_err(struct Context *context, const char* message)
+{
+	null_check(context);
+    struct variable *v = variable_new(context, VAR_ERR);
+    v->str = byte_array_from_string(message);
+    return v;
+}
+
+struct variable* variable_new_nil(struct Context *context)
+{
+	null_check(context);
+    return variable_new(context, VAR_NIL);
+}
+
+struct variable* variable_new_int(struct Context *context, int32_t i)
+{
+	null_check(context);
+    struct variable *v = variable_new(context, VAR_INT);
+    v->integer = i;
+    return v;
+}
+
+struct variable* variable_new_bool(struct Context *context, bool b)
+{
+	null_check(context);
+    struct variable *v = variable_new(context, VAR_BOOL);
+    v->boolean = b;
+    return v;
+}
+
+void variable_del(struct Context *context, struct variable *v)
+{
+	null_check(context);
+    context->num_vars--;
+    switch (v->type) {
+        case VAR_INT:
+        case VAR_FLT:
+        case VAR_MAP:
+            break;
+        case VAR_STR:
+        case VAR_FNC:
+            byte_array_del(v->str);
+            break;
+        case VAR_LST:
+            for (int i=0; i<v->list->length; i++)
+                variable_del(context, (struct variable*)array_get(v->list, i));
+            break;
+        default:
+            vm_exit_message(context, "bad var type");
+            break;
+    }
+    if (v->map) {
+        struct array *keys = map_keys(v->map);
+        struct array *values = map_values(v->map);
+        for (int i=0; i<keys->length; i++) {
+            byte_array_del((struct byte_array*)array_get(keys, i));
+            variable_del(context, (struct variable*)array_get(values, i));
+        }
+        array_del(keys);
+        array_del(values);
+        map_del(v->map);
+    }
+    free(v);
+}
+
+struct variable* variable_new_float(struct Context *context, float f)
+{
+	null_check(context);
+    //DEBUGPRINT("new float %f\n", f);
+    struct variable *v = variable_new(context, VAR_FLT);
+    v->floater = f;
+    return v;
+}
+
+struct variable *variable_new_str(struct Context *context, struct byte_array *str) {
+    struct variable *v = variable_new(context, VAR_STR);
+    v->str = str;
+    return v;
+}
+
+struct variable *variable_new_fnc(struct Context *context, struct byte_array *fnc) {
+    struct variable *v = variable_new(context, VAR_FNC);
+    v->str = fnc;
+    return v;
+}
+
+struct variable *variable_new_list(struct Context *context, struct array *list) {
+    struct variable *v = variable_new(context, VAR_LST);
+    v->list = list ? list : array_new();
+    return v;
+}
+
+struct variable *variable_new_map(struct Context *context, struct map *map) {
+    struct variable *v = variable_new(context, VAR_MAP);
+    v->map = map;
+    return v;
+}
+
+struct variable *variable_new_c(struct Context *context, bridge *cfnc) {
+    struct variable *v = variable_new(context, VAR_C);
+    v->cfnc = cfnc;
+    return v;
+}
+
+const char *variable_value_str(struct Context *context, const struct variable* v)
+{
+	null_check(v);
+    char* str = (char*)malloc(100);
+    struct array* list = v->list;
+	
+    enum VarType vt = (enum VarType)v->type;
+    switch (vt) {
+        case VAR_NIL:    sprintf(str, "nil");                                    break;
+        case VAR_INT:    sprintf(str, "%d", v->integer);                         break;
+        case VAR_BOOL:   sprintf(str, "%s", v->boolean ? "true" : "false");      break;
+        case VAR_FLT:    sprintf(str, "%f", v->floater);                         break;
+        case VAR_STR:    sprintf(str, "%s", byte_array_to_string(v->str));       break;
+        case VAR_FNC:    sprintf(str, "f(%dB)", v->str->length);                 break;
+        case VAR_C:      sprintf(str, "c-function");                             break;
+        case VAR_MAP:                                                            break;
+        case VAR_LST: {
+            strcpy(str, "[");
+            vm_null_check(context, list);
+            for (int i=0; i<list->length; i++) {
+                struct variable* element = (struct variable*)array_get(list, i);
+                vm_null_check(context, element);
+                const char *q = (element->type == VAR_STR || element->type == VAR_FNC) ? "'" : "";
+                const char *c = i ? "," : "";
+				const char *estr = variable_value_str(context, element);
+                sprintf(str, "%s%s%s%s%s", str, c, q, estr, q);
+            }
+        } break;
+        case VAR_ERR:
+            strcpy(str, byte_array_to_string(v->str));
+            break;
+        default:
+            vm_exit_message(context, ERROR_VAR_TYPE);
+            break;
+    }
+
+    if (v->map) {
+        const struct array *a = map_keys(v->map);
+        const struct array *b = map_values(v->map);
+		
+        if (vt != VAR_LST)
+            strcat(str, "[");
+        else if (v->list->length && a->length)
+            strcat(str, ",");
+        for (int i=0; i<a->length; i++) {
+            if (i)
+                strcat(str, ",");
+            strcat(str, "'");
+            strcat(str, byte_array_to_string((struct byte_array*)array_get(a,i)));
+            strcat(str, "'");
+            strcat(str, ":");
+			const struct variable *biv = (const struct variable*)array_get(b,i);
+			const char *bistr = variable_value_str(context, biv);
+            strcat(str, bistr);
+        }
+        strcat(str, "]");
+    }
+    else if (vt == VAR_LST)
+        strcat(str, "]");
+
+	return str;
+}
+
+struct byte_array *variable_value(struct Context *c, const struct variable *v) {
+	const char *str = variable_value_str(c, v);
+    return byte_array_from_string(str);
+}
+
+
+
+struct variable *variable_pop(struct Context *context)
+{
+	null_check(context);
+    struct variable *v = (struct variable*)stack_pop(context->operand_stack);
+    //DEBUGPRINT("\nvariable_pop\n");// %s\n", variable_value(v));
+    //    print_operand_stack();
+    return v;
+}
+
+void variable_push(struct Context *context, struct variable *v)
+{
+	null_check(context);
+    stack_push(context->operand_stack, v);
+    //DEBUGPRINT("\nvariable_push\n");
+    //print_operand_stack();
+}
+
+struct byte_array *variable_serialize(struct Context *context, 
+									  struct byte_array *bits,
+                                      const struct variable *in)
+{
+	null_check(context);
+    //DEBUGPRINT("\tserialize:%s\n", variable_value(in));
+    if (!bits)
+        bits = byte_array_new();
+    serial_encode_int(bits, 0, in->type);
+    switch (in->type) {
+        case VAR_INT:    serial_encode_int(bits, 0, in->integer);    break;
+        case VAR_FLT:    serial_encode_float(bits, 0, in->floater);    break;
+        case VAR_STR:
+        case VAR_FNC:    serial_encode_string(bits, 0, in->str);        break;
+        case VAR_LST: {
+            serial_encode_int(bits, 0, in->list->length);
+            for (int i=0; i<in->list->length; i++)
+                variable_serialize(context, bits, (const struct variable*)array_get(in->list, i));
+            if (in->map) {
+                const struct array *keys = map_keys(in->map);
+                const struct array *values = map_values(in->map);
+                serial_encode_int(bits, 0, keys->length);
+                for (int i=0; i<keys->length; i++) {
+                    serial_encode_string(bits, 0, (const struct byte_array*)array_get(keys, i));
+                    variable_serialize(context, bits, (const struct variable*)array_get(values, i));
+                }
+            } else
+                serial_encode_int(bits, 0, 0);
+        } break;
+        case VAR_MAP:                                                break;
+        default:        vm_exit_message(context, "bad var type");                break;
+    }
+	
+    //DEBUGPRINT("in: %s\n", variable_value(in));
+    //byte_array_print("serialized: ", bits);
+    return bits;
+}
+
+struct variable *variable_deserialize(struct Context *context, struct byte_array *bits)
+{
+	null_check(context);
+    enum VarType vt = (enum VarType)serial_decode_int(bits);
+    switch (vt) {
+        case VAR_NIL:    return variable_new_nil(context);
+        case VAR_INT:    return variable_new_int(context, serial_decode_int(bits));
+        case VAR_FLT:    return variable_new_float(context, serial_decode_float(bits));
+        case VAR_FNC:    return variable_new_fnc(context, serial_decode_string(bits));
+        case VAR_STR:    return variable_new_str(context, serial_decode_string(bits));
+        case VAR_LST: {
+            uint32_t size = serial_decode_int(bits);
+            struct array *list = array_new_size(size);
+            while (size--)
+                array_add(list, variable_deserialize(context, bits));
+            struct variable *out = variable_new_list(context, list);
+			
+            uint32_t map_length = serial_decode_int(bits);
+            if (map_length) {
+                out->map = map_new();
+                for (int i=0; i<map_length; i++) {
+                    struct byte_array *key = serial_decode_string(bits);
+                    struct variable *value = variable_deserialize(context, bits);
+                    map_insert(out->map, key, value);
+                }
+            }
+            return out;
+        }
+        default:
+            vm_exit_message(context, "bad var type");
+            return NULL;
+    }
+}
+
+int variable_save(struct Context *context, 
+				  const struct variable *v,
+                  const struct variable *path)
+{
+    vm_null_check(context, v);
+    vm_null_check(context, path);
+	
+    struct byte_array *bytes = byte_array_new();
+    variable_serialize(context, bytes, v);
+    return write_file(path->str, bytes);
+}
+
+struct variable *variable_load(struct Context *context, const struct variable *path)
+{
+	null_check(context);
+    vm_null_check(context, path);
+	
+    struct byte_array *file_bytes = read_file(path->str);
+    if (!file_bytes)
+        return NULL;
+    struct variable *v = variable_deserialize(context, file_bytes);
+    return v;
+}
+