some things
This commit is contained in:
+82
-18
@@ -1,8 +1,8 @@
|
||||
// forward decls -- start
|
||||
void load_built_ins_into_environment(Environment*);
|
||||
int list_length(Ast_Node*);
|
||||
void parse_argument_list(Ast_Node*, Function*);
|
||||
Ast_Node* eval_expr(Ast_Node*, Environment*);
|
||||
void parse_argument_list(Ast_Node*, Function*);
|
||||
int list_length(Ast_Node*);
|
||||
// forward decls -- end
|
||||
|
||||
|
||||
@@ -18,16 +18,16 @@ namespace Parser {
|
||||
int parser_line;
|
||||
int parser_col;
|
||||
|
||||
// NOTE(Felix): In this environment, the build in vunctions will
|
||||
// NOTE(Felix): In this environment, the build in functions will
|
||||
// be loaded, and the macros will be stroed in form of
|
||||
// special-lambdas, that get executed in this environment at
|
||||
// read-time
|
||||
// read-time. This should always be the global environment.
|
||||
Environment* environment_for_macros;
|
||||
|
||||
void init(Environment* env) {
|
||||
// if we already initialized it, then skip
|
||||
if (environment_for_macros)
|
||||
return;
|
||||
// NOTE(Felix): it is important to keep the parser environment
|
||||
// up to date with the global environment. When donig tests,
|
||||
// or running a programm we have to reaload it.
|
||||
|
||||
// NOTE(Felix): For now we just allow executing built-ins at
|
||||
// read-time (while creating macros). If later we want to
|
||||
@@ -148,6 +148,10 @@ namespace Parser {
|
||||
*str = '\0';
|
||||
Ast_Node* ret = create_ast_node_string(str, 0);
|
||||
inject_scl(ret);
|
||||
|
||||
// plus one because we want to go after the quotes
|
||||
*index_in_text += 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -219,11 +223,19 @@ namespace Parser {
|
||||
Ast_Node* parse_expression(char* text, int* index_in_text) {
|
||||
|
||||
// if it is quoted
|
||||
if (text[*index_in_text] == '\'') {
|
||||
if (text[*index_in_text] == '\'' ||
|
||||
text[*index_in_text] == '`' ||
|
||||
text[*index_in_text] == ',')
|
||||
{
|
||||
char quoteType = text[*index_in_text];
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
Ast_Node* result;
|
||||
if (text[*index_in_text] == '(' || text[*index_in_text] == '\'' ) {
|
||||
if (text[*index_in_text] == '(' ||
|
||||
text[*index_in_text] == '\'' ||
|
||||
text[*index_in_text] == '`' ||
|
||||
text[*index_in_text] == ',')
|
||||
{
|
||||
try {
|
||||
result = parse_expression(text, index_in_text);
|
||||
}
|
||||
@@ -232,11 +244,22 @@ namespace Parser {
|
||||
result = parse_atom(text, index_in_text);
|
||||
}
|
||||
}
|
||||
|
||||
if (quoteType == '\'')
|
||||
return create_ast_node_pair(
|
||||
create_ast_node_symbol("quote"),
|
||||
create_ast_node_pair(result, create_ast_node_nil()));
|
||||
else if (quoteType == '`')
|
||||
return create_ast_node_pair(
|
||||
create_ast_node_symbol("quasiquote"),
|
||||
create_ast_node_pair(result, create_ast_node_nil()));
|
||||
// it has to be an unquote
|
||||
return create_ast_node_pair(
|
||||
create_ast_node_symbol("quote"),
|
||||
create_ast_node_symbol("unquote"),
|
||||
create_ast_node_pair(result, create_ast_node_nil()));
|
||||
}
|
||||
|
||||
|
||||
// if it is not quoted
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
@@ -258,7 +281,11 @@ namespace Parser {
|
||||
Ast_Node* expression = head;
|
||||
|
||||
while (true) {
|
||||
if (text[(*index_in_text)] == '(' || text[(*index_in_text)] == '\'' ) {
|
||||
if (text[*index_in_text] == '(' ||
|
||||
text[*index_in_text] == '\''||
|
||||
text[*index_in_text] == '`' ||
|
||||
text[*index_in_text] == ',')
|
||||
{
|
||||
try {
|
||||
head->value.pair->first = parse_expression(text, index_in_text);
|
||||
}
|
||||
@@ -333,7 +360,7 @@ namespace Parser {
|
||||
|
||||
Function* function = new(Function);
|
||||
function->parent_environment = environment_for_macros;
|
||||
function->is_special_form = true;
|
||||
function->type = Function_Type::Macro;
|
||||
|
||||
// if parameters were specified
|
||||
if (arguments->value.pair->first->type != Ast_Node_Type::Nil) {
|
||||
@@ -393,14 +420,20 @@ namespace Parser {
|
||||
|
||||
for (int i = 0; i < environment_for_macros->next_index; ++i) {
|
||||
if (string_equal(expression->value.pair->first->value.symbol->identifier, environment_for_macros->keys[i]) &&
|
||||
environment_for_macros->values[i]->type == Ast_Node_Type::Function)
|
||||
environment_for_macros->values[i]->type == Ast_Node_Type::Function &&
|
||||
environment_for_macros->values[i]->value.function->type == Function_Type::Macro)
|
||||
{
|
||||
// every `Function` that is defined in this
|
||||
// environment _has_ to be a macro because
|
||||
// only built_ins are in there otherwise,
|
||||
// which are `CFunction`s.
|
||||
try {
|
||||
// if (string_equal(environment_for_macros->keys[i], "when")) {
|
||||
// printf("invoking macro for %s in %s:%d to:\n\t", environment_for_macros->keys[i], parser_file, parser_line);
|
||||
// print(environment_for_macros->values[i]->value.function->body);
|
||||
// }
|
||||
expression = eval_expr(expression, environment_for_macros);
|
||||
// if (string_equal(environment_for_macros->keys[i], "when")) {
|
||||
// printf("\nresult: \n\t");
|
||||
// print(expression);
|
||||
// printf("\n\n");
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,10 +454,15 @@ namespace Parser {
|
||||
eat_until_code(text, &index_in_text);
|
||||
if (text[(index_in_text)] == '\0')
|
||||
return create_ast_node_nil();
|
||||
if (text[(index_in_text)] == '(' || text[(index_in_text)] == '\'' )
|
||||
if (text[index_in_text] == '(' ||
|
||||
text[index_in_text] == '\'' ||
|
||||
text[index_in_text] == '`' ||
|
||||
text[index_in_text] == ',')
|
||||
{
|
||||
try {
|
||||
result = parse_expression(text, &index_in_text);
|
||||
}
|
||||
}
|
||||
else
|
||||
try {
|
||||
result = parse_atom(text, &index_in_text);
|
||||
@@ -436,6 +474,29 @@ namespace Parser {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void write_expanded_file(char* file_name, Ast_Node_Array_List* program) {
|
||||
char* ext = ".expanded";
|
||||
char* newName = (char*)calloc(4 + strlen(file_name), sizeof(char));
|
||||
strcpy(newName, file_name);
|
||||
strcat(newName, ext);
|
||||
|
||||
FILE *f = fopen(newName, "w");
|
||||
if (f == NULL) {
|
||||
printf("Error opening file!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < program->next_index; ++i) {
|
||||
// a macro will parse as nil for now, so we skip those
|
||||
if (program->data[i]->type == Ast_Node_Type::Nil)
|
||||
continue;
|
||||
fprint(f, program->data[i]);
|
||||
fprintf(f, "\n\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
Ast_Node_Array_List* parse_program(char* file_name, char* text) {
|
||||
parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1);
|
||||
strcpy(parser_file, file_name);
|
||||
@@ -468,6 +529,9 @@ namespace Parser {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
write_expanded_file(file_name, program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user