refactor: spread across files
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
|||||||
|
#include "lisp.h"
|
||||||
|
|
||||||
|
Node *lisp_function_addition(Nodes *args) {
|
||||||
|
if (args->count != 2) {
|
||||||
|
printf("'+' expects two arguments!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args->items[0].kind != NODE_KIND_NUMBER ||
|
||||||
|
args->items[1].kind != NODE_KIND_NUMBER) {
|
||||||
|
printf("'+' can only add numbers, you specified something else!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *node = malloc(sizeof(Node));
|
||||||
|
node->kind = NODE_KIND_NUMBER;
|
||||||
|
|
||||||
|
intptr_t a = args->items[0].as_number;
|
||||||
|
intptr_t b = args->items[1].as_number;
|
||||||
|
node->as_number = a + b;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
@@ -1,90 +1,10 @@
|
|||||||
#include <ctype.h>
|
#include "lisp.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define NOB_IMPLEMENTATION
|
|
||||||
#include "nob.h"
|
|
||||||
|
|
||||||
typedef enum e_TokenKind {
|
|
||||||
TOKEN_KIND_PAR_LEFT,
|
|
||||||
TOKEN_KIND_PAR_RIGHT,
|
|
||||||
TOKEN_KIND_NUMBER,
|
|
||||||
TOKEN_KIND_SYMBOL,
|
|
||||||
} TokenKind;
|
|
||||||
|
|
||||||
typedef struct s_Token {
|
|
||||||
TokenKind kind;
|
|
||||||
Nob_String_View data;
|
|
||||||
} Token;
|
|
||||||
|
|
||||||
typedef struct s_Tokens {
|
|
||||||
Token *items;
|
|
||||||
size_t count;
|
|
||||||
size_t capacity;
|
|
||||||
} Tokens;
|
|
||||||
|
|
||||||
typedef enum e_NodeKind {
|
|
||||||
NODE_KIND_SYMBOL,
|
|
||||||
NODE_KIND_LIST,
|
|
||||||
NODE_KIND_NUMBER,
|
|
||||||
NODE_KIND_FUNCTION,
|
|
||||||
} NodeKind;
|
|
||||||
|
|
||||||
typedef struct s_Node Node;
|
|
||||||
typedef struct s_Nodes Nodes;
|
|
||||||
|
|
||||||
typedef Node *(*lisp_function_ptr)(Nodes *args);
|
|
||||||
typedef struct s_LispFunction {
|
|
||||||
Nob_String_View name;
|
|
||||||
lisp_function_ptr apply;
|
|
||||||
} LispFunction;
|
|
||||||
|
|
||||||
typedef struct s_Node {
|
|
||||||
NodeKind kind;
|
|
||||||
union {
|
|
||||||
Nob_String_View as_symbol;
|
|
||||||
Nodes *as_list;
|
|
||||||
long long as_number;
|
|
||||||
LispFunction as_function;
|
|
||||||
};
|
|
||||||
} Node;
|
|
||||||
|
|
||||||
struct s_Nodes {
|
|
||||||
Node *items;
|
|
||||||
size_t count;
|
|
||||||
size_t capacity;
|
|
||||||
};
|
|
||||||
|
|
||||||
Node *lisp_function_addition(Nodes *args) {
|
|
||||||
if (args->count != 2) {
|
|
||||||
printf("'+' expects two arguments!\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args->items[0].kind != NODE_KIND_NUMBER ||
|
|
||||||
args->items[1].kind != NODE_KIND_NUMBER) {
|
|
||||||
printf("'+' can only add numbers, you specified something else!\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node *node = malloc(sizeof(Node));
|
|
||||||
node->kind = NODE_KIND_NUMBER;
|
|
||||||
|
|
||||||
intptr_t a = args->items[0].as_number;
|
|
||||||
intptr_t b = args->items[1].as_number;
|
|
||||||
node->as_number = a + b;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LispFunction globalScope[] = {
|
static LispFunction globalScope[] = {
|
||||||
(LispFunction){.name = (Nob_String_View){.items = "+", .count = 1},
|
(LispFunction){.name = (Nob_String_View){.items = "+", .count = 1},
|
||||||
.apply = lisp_function_addition}};
|
.apply = lisp_function_addition}};
|
||||||
|
|
||||||
Node *lisp_function_lookup(Nob_String_View name) {
|
static Node *lisp_function_lookup(Nob_String_View name) {
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(globalScope); i++) {
|
for (size_t i = 0; i < NOB_ARRAY_LEN(globalScope); i++) {
|
||||||
if (nob_sv_eq(globalScope[i].name, name)) {
|
if (nob_sv_eq(globalScope[i].name, name)) {
|
||||||
Node *node = malloc(sizeof(Node));
|
Node *node = malloc(sizeof(Node));
|
||||||
@@ -113,6 +33,33 @@ const char *token_kind_name(TokenKind kind) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void node_print(Node node) {
|
||||||
|
switch (node.kind) {
|
||||||
|
case NODE_KIND_NUMBER: {
|
||||||
|
printf("%lld", node.as_number);
|
||||||
|
} break;
|
||||||
|
case NODE_KIND_SYMBOL: {
|
||||||
|
printf(SV_Fmt, SV_Arg(node.as_symbol));
|
||||||
|
} break;
|
||||||
|
case NODE_KIND_LIST: {
|
||||||
|
Nodes *children = node.as_list;
|
||||||
|
printf("(");
|
||||||
|
for (size_t i = 0; i < children->count; i++) {
|
||||||
|
Node node = children->items[i];
|
||||||
|
node_print(node);
|
||||||
|
if (i != children->count - 1) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
} break;
|
||||||
|
case NODE_KIND_FUNCTION: {
|
||||||
|
LispFunction func = node.as_function;
|
||||||
|
printf(SV_Fmt, SV_Arg(func.name));
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tokenize(Nob_String_View content, Tokens *tokens) {
|
void tokenize(Nob_String_View content, Tokens *tokens) {
|
||||||
for (size_t i = 0; i < content.count; i++) {
|
for (size_t i = 0; i < content.count; i++) {
|
||||||
char c = content.data[i];
|
char c = content.data[i];
|
||||||
@@ -149,12 +96,13 @@ void tokenize(Nob_String_View content, Tokens *tokens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// symbols shouldn't start with a digit
|
// symbols shouldn't start with a digit
|
||||||
bool condition =
|
bool condition = isascii(c) && !isdigit(c) && !isblank(c) &&
|
||||||
isascii(c) && !isdigit(c) && !isblank(c) && c != '(' && c != ')';
|
!iscntrl(c) && c != '(' && c != ')';
|
||||||
while (condition) {
|
while (condition) {
|
||||||
nob_sb_appendf(&sb, "%c", c);
|
nob_sb_appendf(&sb, "%c", c);
|
||||||
c = content.data[++i];
|
c = content.data[++i];
|
||||||
condition = isascii(c) && !isblank(c) && c != '(' && c != ')';
|
condition = isascii(c) && !isblank(c) && !iscntrl(c) && c != '(' &&
|
||||||
|
c != ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sb.count > 0) {
|
if (sb.count > 0) {
|
||||||
@@ -232,33 +180,6 @@ Node *parse(Tokens *tokens) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_print(Node node) {
|
|
||||||
switch (node.kind) {
|
|
||||||
case NODE_KIND_NUMBER: {
|
|
||||||
printf("%lld", node.as_number);
|
|
||||||
} break;
|
|
||||||
case NODE_KIND_SYMBOL: {
|
|
||||||
printf(SV_Fmt, SV_Arg(node.as_symbol));
|
|
||||||
} break;
|
|
||||||
case NODE_KIND_LIST: {
|
|
||||||
Nodes *children = node.as_list;
|
|
||||||
printf("(");
|
|
||||||
for (size_t i = 0; i < children->count; i++) {
|
|
||||||
Node node = children->items[i];
|
|
||||||
node_print(node);
|
|
||||||
if (i != children->count - 1) {
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf(")");
|
|
||||||
} break;
|
|
||||||
case NODE_KIND_FUNCTION: {
|
|
||||||
LispFunction func = node.as_function;
|
|
||||||
printf(SV_Fmt, SV_Arg(func.name));
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Node *eval(Node *node) {
|
Node *eval(Node *node) {
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -297,33 +218,3 @@ Node *eval(Node *node) {
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
if (argc < 2)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
argv++;
|
|
||||||
const char *line = *argv++;
|
|
||||||
Nob_String_View view = nob_sv_from_cstr(line);
|
|
||||||
|
|
||||||
Tokens tokens = {0};
|
|
||||||
tokenize(view, &tokens);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
for (size_t i = 0; i < tokens.count; i++) {
|
|
||||||
Token tok = tokens.items[i];
|
|
||||||
printf("Token(kind=%s, data=" SV_Fmt ")\n", token_kind_name(tok.kind),
|
|
||||||
SV_Arg(tok.data));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Node *result = parse(&tokens);
|
|
||||||
if (result == NULL)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result = eval(result);
|
|
||||||
node_print(*result);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
#ifndef LISP_H
|
||||||
|
#define LISP_H
|
||||||
|
|
||||||
|
#include "nob.h"
|
||||||
|
|
||||||
|
typedef enum e_TokenKind {
|
||||||
|
TOKEN_KIND_PAR_LEFT,
|
||||||
|
TOKEN_KIND_PAR_RIGHT,
|
||||||
|
TOKEN_KIND_NUMBER,
|
||||||
|
TOKEN_KIND_SYMBOL,
|
||||||
|
} TokenKind;
|
||||||
|
|
||||||
|
typedef struct s_Token {
|
||||||
|
TokenKind kind;
|
||||||
|
Nob_String_View data;
|
||||||
|
} Token;
|
||||||
|
|
||||||
|
typedef struct s_Tokens {
|
||||||
|
Token *items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} Tokens;
|
||||||
|
|
||||||
|
typedef enum e_NodeKind {
|
||||||
|
NODE_KIND_SYMBOL,
|
||||||
|
NODE_KIND_LIST,
|
||||||
|
NODE_KIND_NUMBER,
|
||||||
|
NODE_KIND_FUNCTION,
|
||||||
|
} NodeKind;
|
||||||
|
|
||||||
|
typedef struct s_Node Node;
|
||||||
|
typedef struct s_Nodes Nodes;
|
||||||
|
|
||||||
|
typedef Node *(*lisp_function_ptr)(Nodes *args);
|
||||||
|
typedef struct s_LispFunction {
|
||||||
|
Nob_String_View name;
|
||||||
|
lisp_function_ptr apply;
|
||||||
|
} LispFunction;
|
||||||
|
|
||||||
|
typedef struct s_Node {
|
||||||
|
NodeKind kind;
|
||||||
|
union {
|
||||||
|
Nob_String_View as_symbol;
|
||||||
|
Nodes *as_list;
|
||||||
|
long long as_number;
|
||||||
|
LispFunction as_function;
|
||||||
|
};
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
struct s_Nodes {
|
||||||
|
Node *items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *token_kind_name(TokenKind kind);
|
||||||
|
void node_print(Node node);
|
||||||
|
|
||||||
|
void tokenize(Nob_String_View content, Tokens *tokens);
|
||||||
|
Node *parse(Tokens *tokens);
|
||||||
|
Node *eval(Node *node);
|
||||||
|
|
||||||
|
// builtins
|
||||||
|
Node *lisp_function_addition(Nodes *args);
|
||||||
|
|
||||||
|
#endif // LISP_H
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define NOB_IMPLEMENTATION
|
||||||
|
#include "lisp.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc < 2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
argv++;
|
||||||
|
const char *line = *argv++;
|
||||||
|
Nob_String_View view = nob_sv_from_cstr(line);
|
||||||
|
|
||||||
|
Tokens tokens = {0};
|
||||||
|
tokenize(view, &tokens);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (size_t i = 0; i < tokens.count; i++) {
|
||||||
|
Token tok = tokens.items[i];
|
||||||
|
printf("Token(kind=%s, data=" SV_Fmt ")\n", token_kind_name(tok.kind),
|
||||||
|
SV_Arg(tok.data));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Node *result = parse(&tokens);
|
||||||
|
if (result == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result = eval(result);
|
||||||
|
node_print(*result);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
(
|
||||||
|
println (
|
||||||
|
let (
|
||||||
|
(x 2)
|
||||||
|
)
|
||||||
|
(
|
||||||
|
cond
|
||||||
|
(
|
||||||
|
(= x 2)
|
||||||
|
5
|
||||||
|
)
|
||||||
|
(
|
||||||
|
else
|
||||||
|
1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user