impl scopes more or less properly
This commit is contained in:
+16
-1
@@ -1,6 +1,8 @@
|
|||||||
#include "lisp.h"
|
#include "lisp.h"
|
||||||
|
|
||||||
Node *lisp_function_addition(Nodes *args) {
|
Node *lisp_function_addition(Nodes *args, Scopes *scopes) {
|
||||||
|
(void)(scopes);
|
||||||
|
|
||||||
if (args->count != 2) {
|
if (args->count != 2) {
|
||||||
printf("'+' expects two arguments!\n");
|
printf("'+' expects two arguments!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -20,3 +22,16 @@ Node *lisp_function_addition(Nodes *args) {
|
|||||||
node->as_number = a + b;
|
node->as_number = a + b;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node *lisp_function_println(Nodes *args, Scopes *scopes) {
|
||||||
|
if (args->count != 1) {
|
||||||
|
printf("'+' expects one argument!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *result = eval(&args->items[0], scopes);
|
||||||
|
node_print(*result);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
#include "lisp.h"
|
#include "lisp.h"
|
||||||
|
|
||||||
static LispFunction globalScope[] = {
|
static Scope globalScope = {0};
|
||||||
(LispFunction){.name = (Nob_String_View){.items = "+", .count = 1},
|
|
||||||
.apply = lisp_function_addition}};
|
|
||||||
|
|
||||||
static Node *lisp_function_lookup(Nob_String_View name) {
|
static Node *scope_lookup(Scopes *scopes, Nob_String_View name) {
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(globalScope); i++) {
|
nob_da_foreach(Scope, scope, scopes) {
|
||||||
if (nob_sv_eq(globalScope[i].name, name)) {
|
nob_da_foreach(ScopeObject, scopeObject, scope) {
|
||||||
Node *node = malloc(sizeof(Node));
|
if (nob_sv_eq(name, scopeObject->name)) {
|
||||||
node->kind = NODE_KIND_FUNCTION;
|
return &scopeObject->node;
|
||||||
node->as_function = globalScope[i];
|
}
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,6 +15,44 @@ static Node *lisp_function_lookup(Nob_String_View name) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void build_scopes(Scopes *scopes) {
|
||||||
|
// clang-format off
|
||||||
|
Nob_String_View obj_name = (Nob_String_View){
|
||||||
|
.items = "+",
|
||||||
|
.count = 1
|
||||||
|
};
|
||||||
|
ScopeObject obj = (ScopeObject){
|
||||||
|
.name = obj_name,
|
||||||
|
.node = (Node){
|
||||||
|
.kind = NODE_KIND_FUNCTION,
|
||||||
|
.as_function = {
|
||||||
|
.name = obj_name,
|
||||||
|
.apply = lisp_function_addition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
nob_da_append(&globalScope, obj);
|
||||||
|
|
||||||
|
obj_name = (Nob_String_View){
|
||||||
|
.items = "println",
|
||||||
|
.count = 7
|
||||||
|
};
|
||||||
|
obj = (ScopeObject){
|
||||||
|
.name = obj_name,
|
||||||
|
.node = (Node){
|
||||||
|
.kind = NODE_KIND_FUNCTION,
|
||||||
|
.as_function = {
|
||||||
|
.name = obj_name,
|
||||||
|
.apply = lisp_function_println
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
nob_da_append(&globalScope, obj);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
nob_da_append(scopes, globalScope);
|
||||||
|
}
|
||||||
|
|
||||||
const char *token_kind_name(TokenKind kind) {
|
const char *token_kind_name(TokenKind kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case TOKEN_KIND_PAR_LEFT:
|
case TOKEN_KIND_PAR_LEFT:
|
||||||
@@ -54,8 +89,8 @@ void node_print(Node node) {
|
|||||||
printf(")");
|
printf(")");
|
||||||
} break;
|
} break;
|
||||||
case NODE_KIND_FUNCTION: {
|
case NODE_KIND_FUNCTION: {
|
||||||
LispFunction func = node.as_function;
|
Nob_String_View func_name = node.as_function.name;
|
||||||
printf(SV_Fmt, SV_Arg(func.name));
|
printf(SV_Fmt, SV_Arg(func_name));
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,15 +215,15 @@ Node *parse(Tokens *tokens) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *eval(Node *node) {
|
Node *eval(Node *node, Scopes *scopes) {
|
||||||
if (node == NULL)
|
if (node == NULL || scopes == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case NODE_KIND_NUMBER:
|
case NODE_KIND_NUMBER:
|
||||||
return node;
|
return node;
|
||||||
case NODE_KIND_SYMBOL: {
|
case NODE_KIND_SYMBOL: {
|
||||||
return lisp_function_lookup(node->as_symbol);
|
return scope_lookup(scopes, node->as_symbol);
|
||||||
}
|
}
|
||||||
case NODE_KIND_LIST: {
|
case NODE_KIND_LIST: {
|
||||||
Nodes *children = node->as_list;
|
Nodes *children = node->as_list;
|
||||||
@@ -196,16 +231,15 @@ Node *eval(Node *node) {
|
|||||||
return node;
|
return node;
|
||||||
|
|
||||||
Node *head = &children->items[0];
|
Node *head = &children->items[0];
|
||||||
Node *func_node = eval(head);
|
Node *func_node = eval(head, scopes);
|
||||||
|
|
||||||
Nodes *args = malloc(sizeof(Nodes));
|
Nodes *args = malloc(sizeof(Nodes));
|
||||||
for (size_t i = 1; i < children->count; i++) {
|
for (size_t i = 1; i < children->count; i++) {
|
||||||
nob_da_append(args, *eval(&children->items[i]));
|
nob_da_append(args, *eval(&children->items[i], scopes));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_node->kind == NODE_KIND_FUNCTION) {
|
if (func_node->kind == NODE_KIND_FUNCTION) {
|
||||||
LispFunction func = func_node->as_function;
|
return func_node->as_function.apply(args, scopes);
|
||||||
return func.apply(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Not a function: '");
|
printf("Not a function: '");
|
||||||
|
|||||||
@@ -30,22 +30,22 @@ typedef enum e_NodeKind {
|
|||||||
|
|
||||||
typedef struct s_Node Node;
|
typedef struct s_Node Node;
|
||||||
typedef struct s_Nodes Nodes;
|
typedef struct s_Nodes Nodes;
|
||||||
|
typedef struct s_Scopes Scopes;
|
||||||
|
|
||||||
typedef Node *(*lisp_function_ptr)(Nodes *args);
|
typedef Node *(*LispFunction)(Nodes *args, Scopes *scopes);
|
||||||
typedef struct s_LispFunction {
|
|
||||||
Nob_String_View name;
|
|
||||||
lisp_function_ptr apply;
|
|
||||||
} LispFunction;
|
|
||||||
|
|
||||||
typedef struct s_Node {
|
struct s_Node {
|
||||||
NodeKind kind;
|
NodeKind kind;
|
||||||
union {
|
union {
|
||||||
Nob_String_View as_symbol;
|
Nob_String_View as_symbol;
|
||||||
Nodes *as_list;
|
Nodes *as_list;
|
||||||
long long as_number;
|
long long as_number;
|
||||||
LispFunction as_function;
|
struct {
|
||||||
|
Nob_String_View name;
|
||||||
|
LispFunction apply;
|
||||||
|
} as_function;
|
||||||
};
|
};
|
||||||
} Node;
|
};
|
||||||
|
|
||||||
struct s_Nodes {
|
struct s_Nodes {
|
||||||
Node *items;
|
Node *items;
|
||||||
@@ -53,14 +53,34 @@ struct s_Nodes {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct s_ScopeObject {
|
||||||
|
Nob_String_View name;
|
||||||
|
Node node;
|
||||||
|
} ScopeObject;
|
||||||
|
|
||||||
|
// TODO: use hashtable
|
||||||
|
typedef struct s_Scope {
|
||||||
|
ScopeObject *items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} Scope;
|
||||||
|
|
||||||
|
struct s_Scopes {
|
||||||
|
Scope *items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
const char *token_kind_name(TokenKind kind);
|
const char *token_kind_name(TokenKind kind);
|
||||||
void node_print(Node node);
|
void node_print(Node node);
|
||||||
|
|
||||||
|
void build_scopes(Scopes *scopes);
|
||||||
void tokenize(Nob_String_View content, Tokens *tokens);
|
void tokenize(Nob_String_View content, Tokens *tokens);
|
||||||
Node *parse(Tokens *tokens);
|
Node *parse(Tokens *tokens);
|
||||||
Node *eval(Node *node);
|
Node *eval(Node *node, Scopes *scopes);
|
||||||
|
|
||||||
// builtins
|
// builtins
|
||||||
Node *lisp_function_addition(Nodes *args);
|
Node *lisp_function_addition(Nodes *args, Scopes *scopes);
|
||||||
|
Node *lisp_function_println(Nodes *args, Scopes *scopes);
|
||||||
|
|
||||||
#endif // LISP_H
|
#endif // LISP_H
|
||||||
|
|||||||
@@ -37,11 +37,15 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Scopes scopes = {0};
|
||||||
|
build_scopes(&scopes);
|
||||||
|
|
||||||
Node *result = parse(&tokens);
|
Node *result = parse(&tokens);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
result = eval(result);
|
result = eval(result, &scopes);
|
||||||
|
printf("= ");
|
||||||
node_print(*result);
|
node_print(*result);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user