void ClearAllGC() { unsigned int index; /* contexts */ for (index = 0; index < gGCManager.ctx_size; index++) { CONTEXT* context = gGCManager.contexts[index]; ClearContext(context); } /* functions */ for (index = 0; index < gGCManager.func_size; index++) { FUNCTION* function = gGCManager.functions[index]; ClearFunction(function); } /* dictionaries */ for (index = 0; index < gGCManager.table_size; index++) { HASH_TABLE* table = gGCManager.tables[index]; ClearDictionary(table); } /* strings */ for (index = 0; index < gGCManager.str_size; index++) { char* string = gGCManager.strings[index]; ClearString(string); } /* parse tree */ AST_STORE *cur_ast, *next_ast; cur_ast = gGCManager.parseTrees; while (cur_ast) { next_ast = cur_ast->next; FreeParseTree(cur_ast->parseTree); free(cur_ast); cur_ast = next_ast; } /* lexings */ LEXING_STORE *cur_lex, *next_lex; cur_lex = gGCManager.lexings; while (cur_lex) { next_lex = cur_lex->next; FreeLexing(cur_lex->tokens, cur_lex->buffer); free(cur_lex); cur_lex = next_lex; } }
// parse tree memory management void FreeParseTree(SYNTAX_TREE* ast) { if (ast && ast->children) { int i; for (i = 0; i < ast->numChildren; i++) { FreeParseTree(ast->children[i]); } free(ast->children); free(ast); } else if (ast) { free(ast); } }
/* reduce or remove trivial abstract syntax tree productions */ void ReduceProgramAST(SYNTAX_TREE** program) { const unsigned int empty_production = 0xFF; unsigned int child0_productions[] = {7, 8, 9, 10, 11, 12, 33, 38, 40, 47, 52, 55, 58, 60, 64, 65}; unsigned int child1_productions[] = {19, 24, 30, 59}; unsigned int child2_productions[] = {23}; unsigned int empty_productions[] = {3, 5, 6, 17, 18, 78}; unsigned int i; unsigned int reducible = 1; // continue while reducible while (reducible) { reducible = 0; /* empty productions: 3, 5, 6, 17, 18, 78 */ for (i = 0; i < sizeof(empty_productions)/sizeof(int); i++) { if ((*program)->production == empty_productions[i]) { (*program)->production = empty_production; reducible = 1; } } /* productions that reduce to node->children[0] */ /* 7, 8, 9, 10, 11, 12, 33, 38, 40, 47, 52, 55, 58, 60, 64, 65 */ for (i = 0; i < sizeof(child0_productions)/sizeof(int); i++) { if ((*program)->production == child0_productions[i]) { SYNTAX_TREE* cur = *program; unsigned int child; for (child = 1; child < cur->numChildren; child++) { FreeParseTree(cur->children[child]); } *program = (*program)->children[0]; free(cur->children); free(cur); reducible = 1; } } /* productions that reduce to node->children[1] */ /* 19, 24, 30, 59 */ for (i = 0; i < sizeof(child1_productions)/sizeof(int); i++) { if ((*program)->production == child1_productions[i]) { SYNTAX_TREE* cur = *program; unsigned int child; for (child = 0; child < cur->numChildren; child++) { if (child != 1) { FreeParseTree(cur->children[child]); } } *program = (*program)->children[1]; free(cur->children); free(cur); reducible = 1; } } /* productions that reduce to node->children[2] */ /* 23 */ for (i = 0; i < sizeof(child2_productions)/sizeof(int); i++) { if ((*program)->production == child2_productions[i]) { SYNTAX_TREE* cur = *program; unsigned int child; for (child = 0; child < cur->numChildren; child++) { if (child != 2) { FreeParseTree(cur->children[child]); } } *program = (*program)->children[2]; free(cur->children); free(cur); reducible = 1; } } } // apply for all sub-trees for (i = 0; i < (*program)->numChildren; i++) { ReduceProgramAST(&(*program)->children[i]); } }
/* eval(source) */ int DuckEval(int argument_count, void* data) { L_TOKEN* lexing; SYNTAX_TREE* ast; char* buffer; int error = 0; VALUE argument = GetRecord("source", gCurrentContext); gLastExpression.type = VAL_NIL; gLastExpression.data.primitive = 0; CLOSURE* currentContext; currentContext = gCurrentContext; int prev_line_error = line_error; SYNTAX_TREE* prev_failed_production = failed_production; // if (gCurrentContext->parent) gCurrentContext = gCurrentContext->parent; gCurrentContext = gGlobalContext; if (argument.type == VAL_STRING) { lexing = LexSourceBuffer(argument.data.string, &buffer, CONTEXT_FREE_GRAMMAR); if (lexing == NULL) { printf("Error lexing source or empty source string.\n"); FreeLexing(lexing, buffer); return 1; } ast = ParseSource(lexing, PARSE_TABLE, CONTEXT_FREE_GRAMMAR); if (ast == NULL) { printf("Error parsing source.\n"); FreeLexing(lexing, buffer); return 1; } /* ReduceProgramAST(&ast); */ error = InterpretNode(ast); if (error) { printf("%s\n", ErrorMessage(error)); PrintStackTrace(); FreeLexing(lexing, buffer); FreeParseTree(ast); ClearCallStack(&gStackTrace); line_error = prev_line_error; failed_production = prev_failed_production; return 1; } /* sanitize last expression for use in program */ //gLastExpression = ReallocStrings(gLastExpression); /* free lexing and parse tree */ //FreeLexing(lexing, buffer); //FreeParseTree(ast); GCAddLexing(lexing, buffer); GCAddParseTree(ast); } gCurrentContext = currentContext; return error; }