some things

This commit is contained in:
FelixBrendel
2019-01-18 21:36:13 +01:00
parent 93e180a8f1
commit fec24d11c7
14 changed files with 441 additions and 175 deletions
+82 -18
View File
@@ -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;
}