Scope *context_scope_push(Context *ctx) { Scope *s = scope_create(); Scope *prev = ctx->active_scope; ctx->active_scope = s; if (prev != NULL) { scope_child_add(prev, s); } return s; }
int main(int argc, char** argv) { char* filename = NULL; int repl_flag=0, help_flag=0; struct option long_opts[] = { {"help", no_argument, &help_flag, 1}, {"repl", no_argument, &repl_flag, 1}, {0, 0, 0, 0} }; int cont = 1; while(cont) { int opt_index = 0; switch(getopt_long(argc, argv, "hr", long_opts, &opt_index)) { case -1: cont = 0; break; case 'r': repl_flag = 1; break; case '?': case 'h': return usage(); } } if(optind < argc) filename = argv[optind++]; if((!filename && !repl_flag) || help_flag) return usage(); context* root = context_create(); root->scope = scope_create(NULL); if(filename) run_file(filename, root); if(repl_flag) run_repl(root); context_destroy(root); return 0; }
expr *eval(scope *scope, expr *e) { if (e == NULL) return NULL; switch (e->type) { // String and Integer expressions evaluate to themselves. case STRING_EXPR: case INT_EXPR: case FUNC_EXPR: case BUILTIN_EXPR: case BOOL_EXPR: return e; case SYMBOL_EXPR: { expr *value = scope_lookup(scope, e->string_value); // if (!value) // PANIC("Symbol %s not bound to any value\n", e->string_value); return value; } case CELL_EXPR: { expr *head = eval(scope, e->head); if (head == NULL) PANIC("() is not a function."); if (head->type == BUILTIN_EXPR) { // Call the built-in construct. return head->func_ptr(scope, e->tail); } else if (head->type == FUNC_EXPR) { // Call the function. struct scope *new_scope = scope_create(head->closure); if (islist(head->arguments)) { expr *actuals = e->tail; for (expr *formal = head->arguments; formal != NULL; formal = formal->tail) { expr *formal_expr = formal->head; assert(formal_expr->type == SYMBOL_EXPR); if (actuals != NULL) { // If this is a regular function, evaluate the argument. Otherwise, return expression, // Since macros take in their arguments literally. expr *actual_value = head->ismacro ? actuals->head : eval(scope, actuals->head); // Bind the actual value to the formal symbol. scope_add_mapping(new_scope, formal_expr->string_value, actual_value); // Proceed to the next actual. actuals = actuals->tail; } else { // No more actuals, so simply bind the symbol to the empty list (NIL). scope_add_mapping(new_scope, formal_expr->string_value, NULL); } } } else if (issymbol(head->arguments)) { if (head->ismacro) scope_add_mapping(new_scope, head->arguments->string_value, e->tail); else scope_add_mapping(new_scope, head->arguments->string_value, eval_varargs(scope, e->tail)); } // Evaulate the body of the function struct expr *last_value = NULL; for (struct expr *statement = head->body; statement != NULL; statement = statement->tail) { last_value = eval(new_scope, statement->head); } // If this is a regular function, we simply return the result. return head->ismacro ? eval(scope, last_value) : last_value; } else { PANIC("Tried to execute something which is not a function or a macro."); } } default: PANIC("Unkown expression type.\n"); } }