170 lines
3.8 KiB
C
170 lines
3.8 KiB
C
|
|
#include <stdio.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <defines/MAX_MACRO_DEPTH.h>
|
|
|
|
#include <cmdln/struct.h>
|
|
#include <cmdln/process.h>
|
|
#include <cmdln/free.h>
|
|
|
|
#include <gc/new.h>
|
|
#include <gc/mark_as_mortal.h>
|
|
#include <gc/dec_external_refcount.h>
|
|
#include <gc/free.h>
|
|
|
|
#include <parse/istream/file/new.h>
|
|
#include <parse/istream/read.h>
|
|
#include <parse/istream/free.h>
|
|
|
|
#include <parse/tokenizer/struct.h>
|
|
#include <parse/tokenizer/new.h>
|
|
#include <parse/tokenizer/next.h>
|
|
#include <parse/tokenizer/free.h>
|
|
#include <parse/parse.h>
|
|
|
|
#include <value/prettyprint.h>
|
|
#include <value/environment/new.h>
|
|
#include <value/environment/add_builtins.h>
|
|
|
|
#include <stringtree/prepend.h>
|
|
#include <stringtree/println.h>
|
|
#include <stringtree/free.h>
|
|
|
|
#include "expand_macro.h"
|
|
#include "evaluate.h"
|
|
|
|
int main(
|
|
int argc, char* const* argv)
|
|
{
|
|
unsigned i;
|
|
ENTER;
|
|
|
|
struct cmdln_flags* flags = process_cmdln_flags(argc, argv);
|
|
|
|
struct gc* gc = new_gc(
|
|
/* garbage collection flags: */ &flags->gc_flags);
|
|
|
|
struct value* environments[MAX_MACRO_DEPTH + 1];
|
|
|
|
for (i = 0; i < MAX_MACRO_DEPTH; i++)
|
|
{
|
|
struct value* environment = new_environment_value(
|
|
/* garbage collector: */ gc,
|
|
/* fallback environment: */ NULL);
|
|
|
|
environment_value_add_builtins(
|
|
/* this: */ environment,
|
|
/* macro-depth: */ MAX_MACRO_DEPTH - i);
|
|
|
|
environments[i] = environment;
|
|
}
|
|
|
|
environments[i] = new_environment_value(
|
|
/* garbage collector: */ gc,
|
|
/* fallback environment: */ NULL);
|
|
|
|
environment_value_add_builtins(
|
|
/* this: */ environments[i],
|
|
/* macro-depth (proper evaluation is zero depth): */ 0);
|
|
|
|
struct istream* stream = new_file_istream(
|
|
/* path: */ flags->input_file);
|
|
|
|
istream_read(stream);
|
|
|
|
struct tokenizer* tokenizer = new_tokenizer(stream);
|
|
|
|
tokenizer_next_token(tokenizer);
|
|
|
|
while (tokenizer->token != t_EOF)
|
|
{
|
|
struct value* value = parse(tokenizer, gc);
|
|
|
|
if (flags->verbose)
|
|
{
|
|
struct stringtree* tree = value_prettyprint(value);
|
|
|
|
stringtree_prepend_string_const(tree, "parsed: ");
|
|
|
|
stringtree_println(tree, stdout);
|
|
|
|
free_stringtree(tree);
|
|
}
|
|
|
|
// macro expansions:
|
|
for (i = 0; i < MAX_MACRO_DEPTH; i++)
|
|
{
|
|
struct value* expanded = expand_macro(
|
|
/* expression: */ value,
|
|
/* environment: */ environments[i],
|
|
/* garbage collector/allocator: */ gc);
|
|
|
|
if (flags->verbose)
|
|
{
|
|
struct stringtree* tree = value_prettyprint(expanded);
|
|
|
|
stringtree_prepend_string_const(tree, "macro expanded: ");
|
|
|
|
stringtree_println(tree, stdout);
|
|
|
|
free_stringtree(tree);
|
|
}
|
|
|
|
gc_dec_external_refcount(gc, value), value = expanded;
|
|
}
|
|
|
|
// evaluate:
|
|
struct value* result = evaluate(
|
|
/* expression: */ value,
|
|
/* environment: */ environments[i],
|
|
/* garbage collector/allocator: */ gc);
|
|
|
|
if (flags->verbose)
|
|
{
|
|
struct stringtree* tree = value_prettyprint(result);
|
|
|
|
stringtree_prepend_string_const(tree, "result: ");
|
|
|
|
stringtree_println(tree, stdout);
|
|
|
|
free_stringtree(tree);
|
|
}
|
|
|
|
gc_dec_external_refcount(gc, result);
|
|
gc_dec_external_refcount(gc, value);
|
|
}
|
|
|
|
free_tokenizer(tokenizer);
|
|
|
|
free_istream(stream);
|
|
|
|
free_gc(gc);
|
|
|
|
free_cmdln_flags(flags);
|
|
|
|
EXIT;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|