Skip to content

Commit

Permalink
Merge pull request #19 from ademyro/feature/strings
Browse files Browse the repository at this point in the history
Feature/strings
  • Loading branch information
ademyro authored Oct 25, 2024
2 parents e2b3258 + e30c1ad commit 515cfd3
Show file tree
Hide file tree
Showing 30 changed files with 744 additions and 619 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ add_executable(neve
src/compiler/compiler.c
src/compiler/ctx.c
src/compiler/emit.c
src/compiler/opt.c
src/err/err.c
src/err/render.c
src/ir/ir.c
Expand All @@ -16,6 +15,7 @@ add_executable(neve
src/lexer/lexer.c
src/mem/mem.c
src/runtime/val.c
src/runtime/obj.c
src/vm/debug.c
src/vm/chunk.c
src/vm/vm.c
Expand Down
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,27 @@ fun main
end
```

* Syntactical aesthetics are ultimately subjective, and Neve's syntax may not be considered 'soothing' by everyone.
\* Syntactical aesthetics are ultimately subjective, and Neve's syntax may not be considered 'soothing' by everyone.

## So, what’s happening?

Neve’s compiler is going to be ported from C to Python. This should allow us to implement complex optimizations more
efficiently. We’re doing this because we want Neve to support separate compilation, and in doing so implement further
optimizations on the Neve code before it’s translated to bytecode.

This means that we’re going to introduce two major changes:

* We’re getting rid of the REPL. Having a separate compiler for Neve means longer compilation times, and a less snappy
REPL experience. Moreover, writing the bytecode output to a file and *then* having the Neve interpreter read it isn’t exactly
desirable--we don’t want to create a new file for the tiniest expressions.
* It might be possible to get around that, though. If we can output the bytecode to an array of bytes without needing to
create a new file just for that, and then pass that array to the interpreter, having a REPL might be manageable.
Ideally, we could implement a “REPL mode” for `nevec` that skips through all optimizations, to provide the snappiest
experience.

* Neve will now have two components--`neve` and `nevec`. `nevec` will compile the `.neve` file to a `.geada` bytecode
file, and `neve` will interpret that file. `nevec` will be implemented in Python, but we will immediately work on
self-hosting it (reimplementing it in Neve) the moment we can.

Eventually, Neve will be moved to a GitHub organization instead of sitting on my GitHub account, and once that step
is completed, `neve` and `nevec` will be hosted on two separate projects.
2 changes: 2 additions & 0 deletions include/chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ typedef enum {
OP_SUB,
OP_MUL,
OP_DIV,
OP_CONCAT,
// OP_INTERPOL,
OP_SHL,
OP_SHR,
OP_BIT_AND,
Expand Down
3 changes: 2 additions & 1 deletion include/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "tok.h"
#include "chunk.h"
#include "vm.h"

#define CHECK_PANIC(ctx) \
do { \
Expand All @@ -24,6 +25,6 @@ typedef struct {

Parser newParser();

bool compile(const char *fname, const char *src, Chunk *ch);
bool compile(VM *vm, const char *fname, const char *src, Chunk *ch);

#endif
4 changes: 3 additions & 1 deletion include/ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
#include "err.h"
#include "lexer.h"
#include "type.h"
#include "vm.h"

typedef struct {
VM *vm;
ErrMod errMod;
Parser parser;
Lexer lexer;
Chunk *currCh;
TypeTable *types;
} Ctx;

Ctx newCtx(ErrMod mod, Chunk *ch);
Ctx newCtx(VM *vm, ErrMod mod, Chunk *ch);

#endif
36 changes: 30 additions & 6 deletions include/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@
#include "tok.h"
#include "type.h"

#define NODE_AS_INT(node) ((node)->as.i)
#define NODE_AS_FLOAT(node) ((node)->as.f)
#define NODE_AS_BOOL(node) ((node)->as.b)
#define NODE_AS_NIL(node) ((node)->as.nilLoc)
#define NODE_AS_UNOP(node) ((node)->as.unOp)
#define NODE_AS_BINOP(node) ((node)->as.binOp)
#define NODE_AS_INT(node) ((node)->as.i)
#define NODE_AS_FLOAT(node) ((node)->as.f)
#define NODE_AS_BOOL(node) ((node)->as.b)
#define NODE_AS_NIL(node) ((node)->as.nilLoc)
#define NODE_AS_STR(node) ((node)->as.str)
// #define NODE_AS_INTERPOL(node) ((node)->as.interpol)
#define NODE_AS_UNOP(node) ((node)->as.unOp)
#define NODE_AS_BINOP(node) ((node)->as.binOp)

typedef enum {
NODE_INT,
NODE_FLOAT,
NODE_BOOL,
NODE_NIL,
NODE_STR,
// NODE_INTERPOL,
NODE_UNOP,
NODE_BINOP
} NodeType;
Expand Down Expand Up @@ -45,6 +49,22 @@ typedef struct {
Loc loc;
} Bool;

typedef struct {
Tok str;

bool ownsLexeme;
} Str;

/*
typedef struct {
Tok str;
bool ownsLexeme;
Node *expr;
Node *next;
} Interpol;
*/

typedef struct {
Tok op;
UnOpType opType;
Expand All @@ -64,6 +84,8 @@ struct Node {
Bool b;
UnOp unOp;
BinOp binOp;
Str str;
// Interpol interpol;

Loc nilLoc;
} as;
Expand All @@ -76,6 +98,8 @@ Node *newInt(TypeTable *table, long value, Loc loc);
Node *newFloat(TypeTable *table, double value, Loc loc);
Node *newBool(TypeTable *table, bool value, Loc loc);
Node *newNil(TypeTable *table, Loc loc);
Node *newStr(TypeTable *table, Tok tok);
Node *newInterpol(TypeTable *table, Tok tok, Node *expr, Node *next);
Node *newUnOp(TypeTable *table, Tok op, UnOpType type, Node *operand);
Node *newBinOp(TypeTable *table, Node *left, Tok op, Node *right);

Expand Down
9 changes: 8 additions & 1 deletion include/mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
#define MEM_H

#include "common.h"
#include "val.h"

#define ALLOC(type, size) \
(type *)reallocate(NULL, 0, sizeof (type) * (size))

#define FREE(type, ptr) reallocate(ptr, sizeof (type), 0)

#define GROW_CAP(cap) ((cap) < 8 ? 8 : (cap) * 2)
#define GROW_ARR(type, ptr, oldSize, newSize) \
(type *) reallocate( \
(type *)reallocate( \
ptr, \
sizeof (type) * (oldSize), \
sizeof (type) * (newSize) \
Expand All @@ -15,5 +21,6 @@
reallocate(ptr, sizeof (type) * (oldSize), 0)

void *reallocate(void *ptr, size_t oldSize, size_t newSize);
void freeObjs(Obj *objs);

#endif
48 changes: 48 additions & 0 deletions include/obj.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef OBJ_H
#define OBJ_H

#include "common.h"
#include "val.h"
#include "vm.h"

#define OBJ_TYPE(val) (VAL_AS_OBJ(val)->type)

#define VAL_AS_STR(val) ((ObjStr *)VAL_AS_OBJ(val))
#define VAL_AS_CSTR(val) (((ObjStr *)VAL_AS_OBJ(val))->chars)

typedef enum {
OBJ_STR
} ObjType;

struct Obj {
ObjType type;

struct Obj *next;
};

struct ObjStr {
Obj obj;

bool ownsStr;
size_t length;
const char *chars;
};

/*
we don’t need this function thanks to type checking, but if it
ends up being absolutely necessary... let’s just keep it in
here for now.
static inline bool isObjType(Val val, ObjType type) {
return IS_VAL_OBJ(val) && OBJ_TYPE(val) == type;
}
*/

ObjStr *allocStr(VM *vm, bool ownsStr, const char *chars, size_t length);

void printObj(Val val);

void freeObj(Obj *obj);

size_t objAsStr(const char *buffer, Obj *obj);

#endif
10 changes: 0 additions & 10 deletions include/opt.h

This file was deleted.

2 changes: 2 additions & 0 deletions include/tok.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,6 @@ Tok emptyTok();

char *copyLexeme(Tok tok);

void trimStrTokQuotes(Tok *tok);

#endif
7 changes: 3 additions & 4 deletions include/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ typedef enum {
TYPE_INT,
TYPE_FLOAT,
TYPE_BOOL,
TYPE_NIL
TYPE_NIL,
TYPE_STR
} TypeKind;

typedef struct {
Expand All @@ -29,13 +30,11 @@ typedef struct {
Type *floatType;
Type *boolType;
Type *nilType;
Type *strType;
} TypeTable;

TypeTable *allocTypeTable();

// future signature: bool getType(char *name, Type *t)
bool getType(TypeTable *table, TypeKind kind, Type *t);

bool typesMatch(Type a, Type b);
bool isTypeKnown(Type t);

Expand Down
11 changes: 10 additions & 1 deletion include/val.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@

#include "common.h"

typedef struct Obj Obj;
typedef struct ObjStr ObjStr;

#define BOOL_VAL(val) ((Val){ VAL_BOOL, {.boolean = (val) } })
#define NIL_VAL ((Val){ VAL_NIL, { .num = 0 } })
#define NUM_VAL(val) ((Val){ VAL_NUM, { .num = (val) } })
#define OBJ_VAL(val) ((Val){ VAL_OBJ, { .obj = (Obj *)(val) } })

#define IS_VAL_BOOL(val) ((val).type == VAL_BOOL)
#define IS_VAL_NIL(val) ((val).type == VAL_NIL)
#define IS_VAL_NUM(val) ((val).type == VAL_NUM)
#define IS_VAL_OBJ(val) ((val).type == VAL_OBJ)

#define VAL_AS_BOOL(val) ((val).as.boolean)
#define VAL_AS_NUM(val) ((val).as.num)
#define VAL_AS_OBJ(val) ((val).as.obj)

typedef enum {
VAL_NUM,
VAL_BOOL,
VAL_NIL
VAL_NIL,
VAL_OBJ
} ValType;

typedef struct {
Expand All @@ -26,6 +33,7 @@ typedef struct {
union {
bool boolean;
double num;
Obj *obj;
} as;
} Val;

Expand All @@ -42,5 +50,6 @@ void freeValArr(ValArr *arr);
void printVal(Val val);

bool valsEq(Val a, Val b);
size_t valAsStr(char *buffer, Val val);

#endif
2 changes: 2 additions & 0 deletions include/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ typedef struct {

Val stack[STACK_MAX];
Val *stackTop;

Obj *objs;
} VM;

typedef enum {
Expand Down
Loading

0 comments on commit 515cfd3

Please sign in to comment.