forked from Mirror/wren
Move value/object stuff to separate files.
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
|
||||
#include "compiler.h"
|
||||
#include "primitives.h"
|
||||
#include "value.h"
|
||||
|
||||
#define PRIMITIVE(cls, name, prim) \
|
||||
{ \
|
||||
|
||||
19
src/value.c
Normal file
19
src/value.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include "value.h"
|
||||
|
||||
int valueIsFn(Value value)
|
||||
{
|
||||
return value.type == VAL_OBJ && value.obj->type == OBJ_FN;
|
||||
}
|
||||
|
||||
int valueIsString(Value value)
|
||||
{
|
||||
return value.type == VAL_OBJ && value.obj->type == OBJ_STRING;
|
||||
}
|
||||
|
||||
Value objectToValue(Obj* obj)
|
||||
{
|
||||
Value value;
|
||||
value.type = VAL_OBJ;
|
||||
value.obj = obj;
|
||||
return value;
|
||||
}
|
||||
153
src/value.h
Normal file
153
src/value.h
Normal file
@ -0,0 +1,153 @@
|
||||
#ifndef wren_value_h
|
||||
#define wren_value_h
|
||||
|
||||
// TODO(bob): This should be in VM. (Or, really, we shouldn't hardcode this at
|
||||
// all and have growable symbol tables.)
|
||||
#define MAX_SYMBOLS 256
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VAL_FALSE,
|
||||
VAL_NULL,
|
||||
VAL_NUM,
|
||||
VAL_TRUE,
|
||||
VAL_OBJ
|
||||
} ValueType;
|
||||
|
||||
typedef enum {
|
||||
OBJ_CLASS,
|
||||
OBJ_FN,
|
||||
OBJ_INSTANCE,
|
||||
OBJ_STRING
|
||||
} ObjType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// The object has been marked during the mark phase of GC.
|
||||
FLAG_MARKED = 0x01,
|
||||
} ObjFlags;
|
||||
|
||||
typedef struct sObj
|
||||
{
|
||||
ObjType type;
|
||||
ObjFlags flags;
|
||||
|
||||
// The next object in the linked list of all currently allocated objects.
|
||||
struct sObj* next;
|
||||
} Obj;
|
||||
|
||||
// TODO(bob): Temp.
|
||||
typedef struct
|
||||
{
|
||||
ValueType type;
|
||||
double num;
|
||||
Obj* obj;
|
||||
} Value;
|
||||
|
||||
typedef struct sVM VM;
|
||||
typedef struct sFiber Fiber;
|
||||
|
||||
typedef Value (*Primitive)(VM* vm, Fiber* fiber, Value* args);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
unsigned char* bytecode;
|
||||
Value* constants;
|
||||
int numConstants;
|
||||
} ObjFn;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
METHOD_NONE,
|
||||
METHOD_PRIMITIVE,
|
||||
METHOD_BLOCK
|
||||
} MethodType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MethodType type;
|
||||
union
|
||||
{
|
||||
Primitive primitive;
|
||||
ObjFn* fn;
|
||||
};
|
||||
} Method;
|
||||
|
||||
typedef struct sObjClass
|
||||
{
|
||||
Obj obj;
|
||||
struct sObjClass* metaclass;
|
||||
struct sObjClass* superclass;
|
||||
// TODO(bob): Hack. Probably don't want to use this much space.
|
||||
Method methods[MAX_SYMBOLS];
|
||||
} ObjClass;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
ObjClass* classObj;
|
||||
// TODO(bob): Fields.
|
||||
} ObjInstance;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
char* value;
|
||||
} ObjString;
|
||||
|
||||
// Get the class value of [value] (0 or 1), which must be a boolean.
|
||||
#define AS_CLASS(value) ((ObjClass*)(value).obj)
|
||||
|
||||
// Get the bool value of [obj] (0 or 1), which must be a boolean.
|
||||
#define AS_BOOL(value) ((value).type == VAL_TRUE)
|
||||
|
||||
// Get the function value of [obj] (0 or 1), which must be a function.
|
||||
#define AS_FN(value) ((ObjFn*)(value).obj)
|
||||
|
||||
// Get the double value of [obj], which must be a number.
|
||||
#define AS_INSTANCE(value) ((ObjInstance*)(value).obj)
|
||||
|
||||
// Get the double value of [value], which must be a number.
|
||||
#define AS_NUM(v) ((v).num)
|
||||
|
||||
// Get the const char* value of [v], which must be a string.
|
||||
#define AS_CSTRING(v) (AS_STRING(v)->value)
|
||||
|
||||
// Get the ObjString* of [v], which must be a string.
|
||||
#define AS_STRING(v) ((ObjString*)(v).obj)
|
||||
|
||||
// Determines if [value] is a garbage-collected object or not.
|
||||
#define IS_OBJ(value) ((value).type == VAL_OBJ)
|
||||
|
||||
#define IS_NULL(value) ((value).type == VAL_NULL)
|
||||
#define IS_NUM(value) ((value).type == VAL_NUM)
|
||||
#define IS_BOOL(value) ((value).type == VAL_FALSE || (value).type == VAL_TRUE)
|
||||
|
||||
// Returns non-zero if [value] is a function object.
|
||||
#define IS_FN(value) (valueIsFn(value))
|
||||
|
||||
// Returns non-zero if [value] is a string object.
|
||||
#define IS_STRING(value) (valueIsString(value))
|
||||
|
||||
// Convert [obj], an `Obj*`, to a [Value].
|
||||
#define OBJ_VAL(obj) (objectToValue((Obj*)(obj)))
|
||||
|
||||
// Convert [boolean], an int, to a boolean [Value].
|
||||
#define BOOL_VAL(boolean) (boolean ? TRUE_VAL : FALSE_VAL)
|
||||
|
||||
// Convert [n], a raw number, to a [Value].
|
||||
#define NUM_VAL(n) ((Value){ VAL_NUM, n, NULL })
|
||||
|
||||
// TODO(bob): Not C89!
|
||||
#define FALSE_VAL ((Value){ VAL_FALSE, 0.0, NULL })
|
||||
#define NULL_VAL ((Value){ VAL_NULL, 0.0, NULL })
|
||||
#define TRUE_VAL ((Value){ VAL_TRUE, 0.0, NULL })
|
||||
// TODO(bob): Gross.
|
||||
#define NO_VAL ((Value){ VAL_OBJ, 0.0, NULL })
|
||||
|
||||
int valueIsFn(Value value);
|
||||
int valueIsString(Value value);
|
||||
Value objectToValue(Obj* obj);
|
||||
|
||||
#endif
|
||||
8
src/vm.c
8
src/vm.c
@ -8,14 +8,6 @@
|
||||
|
||||
static Value primitive_metaclass_new(VM* vm, Fiber* fiber, Value* args);
|
||||
|
||||
Value objectToValue(Obj* obj)
|
||||
{
|
||||
Value value;
|
||||
value.type = VAL_OBJ;
|
||||
value.obj = obj;
|
||||
return value;
|
||||
}
|
||||
|
||||
VM* newVM()
|
||||
{
|
||||
// TODO(bob): Get rid of explicit malloc() here.
|
||||
|
||||
140
src/vm.h
140
src/vm.h
@ -1,135 +1,13 @@
|
||||
#ifndef wren_vm_h
|
||||
#define wren_vm_h
|
||||
|
||||
#include "value.h"
|
||||
|
||||
// TODO(bob): Make these externally controllable.
|
||||
#define STACK_SIZE 1024
|
||||
#define MAX_CALL_FRAMES 256
|
||||
#define MAX_SYMBOLS 256
|
||||
#define MAX_PINNED 16
|
||||
|
||||
// Get the class value of [value] (0 or 1), which must be a boolean.
|
||||
#define AS_CLASS(value) ((ObjClass*)(value).obj)
|
||||
|
||||
// Get the bool value of [obj] (0 or 1), which must be a boolean.
|
||||
#define AS_BOOL(value) ((value).type == VAL_TRUE)
|
||||
|
||||
// Get the function value of [obj] (0 or 1), which must be a function.
|
||||
#define AS_FN(value) ((ObjFn*)(value).obj)
|
||||
|
||||
// Get the double value of [obj], which must be a number.
|
||||
#define AS_INSTANCE(value) ((ObjInstance*)(value).obj)
|
||||
|
||||
// Get the double value of [value], which must be a number.
|
||||
#define AS_NUM(v) ((v).num)
|
||||
|
||||
// Get the const char* value of [v], which must be a string.
|
||||
#define AS_CSTRING(v) (AS_STRING(v)->value)
|
||||
|
||||
// Get the ObjString* of [v], which must be a string.
|
||||
#define AS_STRING(v) ((ObjString*)(v).obj)
|
||||
|
||||
// Determines if [value] is a garbage-collected object or not.
|
||||
#define IS_OBJ(value) ((value).type == VAL_OBJ)
|
||||
|
||||
#define IS_NULL(value) ((value).type == VAL_NULL)
|
||||
#define IS_NUM(value) ((value).type == VAL_NUM)
|
||||
#define IS_BOOL(value) ((value).type == VAL_FALSE || (value).type == VAL_TRUE)
|
||||
|
||||
// TODO(bob): Evaluating value here twice sucks.
|
||||
#define IS_FN(value) (IS_OBJ(value) && (value).obj->type == OBJ_FN)
|
||||
#define IS_STRING(value) (IS_OBJ(value) && (value).obj->type == OBJ_STRING)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VAL_FALSE,
|
||||
VAL_NULL,
|
||||
VAL_NUM,
|
||||
VAL_TRUE,
|
||||
VAL_OBJ
|
||||
} ValueType;
|
||||
|
||||
typedef enum {
|
||||
OBJ_CLASS,
|
||||
OBJ_FN,
|
||||
OBJ_INSTANCE,
|
||||
OBJ_STRING
|
||||
} ObjType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// The object has been marked during the mark phase of GC.
|
||||
FLAG_MARKED = 0x01,
|
||||
} ObjFlags;
|
||||
|
||||
typedef struct sObj
|
||||
{
|
||||
ObjType type;
|
||||
ObjFlags flags;
|
||||
|
||||
// The next object in the linked list of all currently allocated objects.
|
||||
struct sObj* next;
|
||||
} Obj;
|
||||
|
||||
// TODO(bob): Temp.
|
||||
typedef struct
|
||||
{
|
||||
ValueType type;
|
||||
double num;
|
||||
Obj* obj;
|
||||
} Value;
|
||||
|
||||
typedef struct sVM VM;
|
||||
typedef struct sFiber Fiber;
|
||||
|
||||
typedef Value (*Primitive)(VM* vm, Fiber* fiber, Value* args);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
unsigned char* bytecode;
|
||||
Value* constants;
|
||||
int numConstants;
|
||||
} ObjFn;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
METHOD_NONE,
|
||||
METHOD_PRIMITIVE,
|
||||
METHOD_BLOCK
|
||||
} MethodType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MethodType type;
|
||||
union
|
||||
{
|
||||
Primitive primitive;
|
||||
ObjFn* fn;
|
||||
};
|
||||
} Method;
|
||||
|
||||
typedef struct sObjClass
|
||||
{
|
||||
Obj obj;
|
||||
struct sObjClass* metaclass;
|
||||
struct sObjClass* superclass;
|
||||
// TODO(bob): Hack. Probably don't want to use this much space.
|
||||
Method methods[MAX_SYMBOLS];
|
||||
} ObjClass;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
ObjClass* classObj;
|
||||
// TODO(bob): Fields.
|
||||
} ObjInstance;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
char* value;
|
||||
} ObjString;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// Load the constant at index [arg].
|
||||
@ -276,20 +154,6 @@ struct sFiber
|
||||
int numFrames;
|
||||
};
|
||||
|
||||
// TODO(bob): Temp.
|
||||
#define OBJ_VAL(obj) (objectToValue((Obj*)(obj)))
|
||||
Value objectToValue(Obj* obj);
|
||||
|
||||
// TODO(bob): Not C89!
|
||||
#define FALSE_VAL ((Value){ VAL_FALSE, 0.0, NULL })
|
||||
#define NULL_VAL ((Value){ VAL_NULL, 0.0, NULL })
|
||||
#define TRUE_VAL ((Value){ VAL_TRUE, 0.0, NULL })
|
||||
// TODO(bob): Gross.
|
||||
#define NO_VAL ((Value){ VAL_OBJ, 0.0, NULL })
|
||||
|
||||
#define BOOL_VAL(b) (b ? TRUE_VAL : FALSE_VAL)
|
||||
#define NUM_VAL(n) ((Value){ VAL_NUM, n, NULL })
|
||||
|
||||
VM* newVM();
|
||||
void freeVM(VM* vm);
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
292A45D51838566F00C34813 /* value.c in Sources */ = {isa = PBXBuildFile; fileRef = 292A45D41838566F00C34813 /* value.c */; };
|
||||
29AB1F291816E49C004B501E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 29AB1F201816E49C004B501E /* main.c */; };
|
||||
29AB1F2F1816FA66004B501E /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29AB1F2E1816FA66004B501E /* vm.c */; };
|
||||
29AB1F3218170104004B501E /* compiler.c in Sources */ = {isa = PBXBuildFile; fileRef = 29AB1F3018170104004B501E /* compiler.c */; };
|
||||
@ -26,6 +27,8 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
292A45D31838566400C34813 /* value.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = value.h; path = src/value.h; sourceTree = SOURCE_ROOT; };
|
||||
292A45D41838566F00C34813 /* value.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = value.c; path = src/value.c; sourceTree = SOURCE_ROOT; };
|
||||
296681E2183283A500C1407C /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = common.h; path = src/common.h; sourceTree = SOURCE_ROOT; };
|
||||
29AB1F061816E3AD004B501E /* wren */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = wren; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
29AB1F201816E49C004B501E /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = src/main.c; sourceTree = SOURCE_ROOT; };
|
||||
@ -75,6 +78,8 @@
|
||||
29AB1F201816E49C004B501E /* main.c */,
|
||||
29AB1F2E1816FA66004B501E /* vm.c */,
|
||||
29AB1F2D1816FA5B004B501E /* vm.h */,
|
||||
292A45D41838566F00C34813 /* value.c */,
|
||||
292A45D31838566400C34813 /* value.h */,
|
||||
);
|
||||
name = src;
|
||||
path = wren;
|
||||
@ -131,6 +136,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
292A45D51838566F00C34813 /* value.c in Sources */,
|
||||
29AB1F291816E49C004B501E /* main.c in Sources */,
|
||||
29FA7298181D91020089013C /* primitives.c in Sources */,
|
||||
29AB1F3218170104004B501E /* compiler.c in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user