Skip to content

Commit

Permalink
[pirc/new] refactor a bit and do some optimization.
Browse files Browse the repository at this point in the history
+ start of implementing string reuse
+ reusing invocation object, preventing allocation during runtime.
+ added memory freeing functions.

git-svn-id: https://svn.parrot.org/parrot/trunk@31176 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information
kjs committed Sep 16, 2008
1 parent 09736ea commit fa6b002
Show file tree
Hide file tree
Showing 10 changed files with 693 additions and 549 deletions.
20 changes: 15 additions & 5 deletions compilers/pirc/new/main.c
Expand Up @@ -40,8 +40,6 @@
#include "piryy.h"




/*
=head1 FUNCTIONS
Expand Down Expand Up @@ -112,6 +110,14 @@ typedef struct parser_args {

} parser_args;


/*
This will be the proper declaration after testing for thread-safety:
void parse_file(int flexdebug, FILE *infile, char * const filename)
*/
void *
parse_file(void *a) {
yyscan_t yyscanner;
Expand Down Expand Up @@ -153,16 +159,20 @@ parse_file(void *a) {
else
fprintf(stderr, "There were %d errors\n", lexer->parse_errors);


fclose(infile);



/* clean up after playing */
release_resources(lexer);
yylex_destroy(yyscanner);
free(lexer);

return NULL;

}



/*
=item C<int main(int argc, char *argv[])>
Expand All @@ -183,6 +193,7 @@ main(int argc, char *argv[]) {
argc--;
argv++;


/* very basic argument handling; I'm too lazy to check out
* the standard funtion for that, right now. This is a TODO. */
while (argc > 0 && argv[0][0] == '-') {
Expand Down Expand Up @@ -291,7 +302,6 @@ main(int argc, char *argv[]) {
}
#endif


return 0;
}

Expand Down
62 changes: 3 additions & 59 deletions compilers/pirc/new/pir.l
Expand Up @@ -77,62 +77,6 @@ extern void yyset_extra(YY_EXTRA_TYPE lexer, yyscan_t scanner);
#endif



/*
=head1 FUNCTIONS
=over 4
=item C<static char *
dupstr(char const * const source)>
The C89 standard does not define a strdup() in the C library,
so define our own strdup. Function names beginning with "str"
are reserved, so make it dupstr, as that is what it
does: duplicate a string.
=cut
*/
static char *
dupstr(char const * const source) {
char *newstring = (char *)calloc(strlen(source) + 1, sizeof (char));
assert(newstring);
strcpy(newstring, source);
return newstring;
}

/*
=item C<static char *
dupstrn(char const * const source, size_t num_chars)>
See dupstr, except that this version takes the number of characters to be
copied. Easy for copying a string except the quotes, for instance.
=cut
*/
static char *
dupstrn(char const * const source, size_t num_chars) {
char *newstring = (char *)calloc(num_chars + 1, sizeof (char));
assert(newstring);
/* only copy num_chars characters */
strncpy(newstring, source, num_chars);
return newstring;
}

/*
=back
=cut
*/



%}

ALPHA [a-zA-Z@_]
Expand Down Expand Up @@ -336,7 +280,7 @@ Q_STRING {SQ_STRING}|{DQ_STRING}


{Q_STRING} { /* copy the string, remove the quotes. */
yylval->sval = dupstrn(yytext + 1, yyleng - 2);
yylval->sval = dupstrn(yyget_extra(yyscanner), yytext + 1, yyleng - 2);
return TK_STRINGC;
}

Expand All @@ -346,12 +290,12 @@ Q_STRING {SQ_STRING}|{DQ_STRING}
"$I"{DIGIT}+ { yylval->ival = atoi(yytext + 2); return TK_IREG; }

{IDENT}":" { /* make the label Id available in the parser. remove the ":" first. */
yylval->sval = dupstrn(yytext, yyleng - 1);
yylval->sval = dupstrn(yyget_extra(yyscanner), yytext, yyleng - 1);
return TK_LABEL;
}

{IDENT} { /* identifier; can be a global (sub or const), local or parrot op */
yylval->sval = dupstr(yytext);
yylval->sval = dupstr(yyget_extra(yyscanner), yytext);
return TK_IDENT;
}

Expand Down
16 changes: 8 additions & 8 deletions compilers/pirc/new/pir.y
Expand Up @@ -1595,14 +1595,14 @@ identifier : TK_IDENT
| keyword
;

keyword : "if" { $$ = "if"; }
| "unless" { $$ = "unless"; }
| "goto" { $$ = "goto"; }
| "int" { $$ = "int"; }
| "num" { $$ = "num"; }
| "string" { $$ = "string"; }
| "pmc" { $$ = "pmc"; }
| "null" { $$ = "null"; }
keyword : "if" { $$ = dupstr(lexer, "if"); }
| "unless" { $$ = dupstr(lexer, "unless"); }
| "goto" { $$ = dupstr(lexer, "goto"); }
| "int" { $$ = dupstr(lexer, "int"); }
| "num" { $$ = dupstr(lexer, "num"); }
| "string" { $$ = dupstr(lexer, "string"); }
| "pmc" { $$ = dupstr(lexer, "pmc"); }
| "null" { $$ = dupstr(lexer, "null"); }
;

unop : '-' { $$ = "neg"; }
Expand Down
173 changes: 173 additions & 0 deletions compilers/pirc/new/pircompiler.c
Expand Up @@ -42,6 +42,9 @@ new_lexer(char * const filename) {
exit(EXIT_FAILURE);
}

/* create a hashtable to store all strings */
lexer->obj_cache.str_cache = pmc_new(lexer->interp, enum_class_Hash);

return lexer;
}

Expand Down Expand Up @@ -71,6 +74,176 @@ pirerror(lexer_state * const lexer, char const * const message, ...) {
++lexer->parse_errors;
}

/*
=item C<char *
dupstr(char const * const source)>
The C89 standard does not define a strdup() in the C library,
so define our own strdup. Function names beginning with "str"
are reserved, so make it dupstr, as that is what it
does: duplicate a string.
=cut
*/
char *
dupstr(lexer_state * const lexer, char * source) {
return dupstrn(lexer, source, strlen(source));
}

static void
store_string(lexer_state * const lexer, char * const str) {

}

static char *
find_string(lexer_state * const lexer) {
return NULL;
}

/*
=item C<char *
dupstrn(char const * const source, size_t num_chars)>
See dupstr, except that this version takes the number of characters to be
copied. Easy for copying a string except the quotes, for instance.
=cut
*/
char *
dupstrn(lexer_state * const lexer, char * source, size_t num_chars) {
char *result = find_string(lexer);

if (result == NULL) { /* not found */
result = (char *)calloc(num_chars + 1, sizeof (char));
assert(result);
/* only copy num_chars characters */
strncpy(result, source, num_chars);
/* cache the string */
store_string(lexer, result);
}

return result;
}


/***** routine to free memory *****/

void
free_key(key *k) {
free(k);
k = NULL;
}

void
free_constant(constant *c) {
free(c);
c = NULL;
}

void
free_target(target *t) {
if (t->key)
free_key(t->key);

if (t->alias)
free(t->alias);

if (t->lex_name)
free(t->lex_name);

free(t);
t = NULL;
}

void
free_expression(expression *expr) {
switch (expr->type) {
case EXPR_TARGET:
free_target(expr->expr.t);
break;
case EXPR_CONSTANT:
free_constant(expr->expr.c);
break;
case EXPR_KEY:
free_key(expr->expr.k);
break;
default:
break;
}
}

void
free_operands(expression *expr) {
expression *iter = expr;

do {
expression *temp = iter;
iter = iter->next;

free_expression(iter);
free(temp);
}
while (iter != expr);

expr = NULL;
}


void
free_statements(statement *instr) {
statement *iter = instr;
do {
statement *temp = iter;
iter = iter->next;

free_operands(iter->ins->operands);
free(temp);
}
while (iter != instr);

instr = NULL;
}

/*
=item C<void
release_resources(lexer_state *lexer)>
=cut
*/
void
release_resources(lexer_state *lexer) {
subroutine *iter = lexer->subs;

if (iter) {
do {
subroutine *temp = iter;
iter = iter->next;
/* free the symbols in this subroutine */
free_symbols(iter->symbols);

/* free instructions in this subroutine */
free_statements(iter->statements);

/* free this subroutine itself */
free(temp);
}
while (iter != lexer->subs);
}


Parrot_destroy(lexer->interp);

/* finally, free the lexer itself */
free(lexer);

lexer = NULL;
}

/*
Expand Down
18 changes: 18 additions & 0 deletions compilers/pirc/new/pircompiler.h
Expand Up @@ -16,6 +16,16 @@

#include <stdio.h> /* for FILE * */


/* a cache stores can store objects to reuse; for now, only for invocation objects */
typedef struct cache {
invocation inv_cache;
PMC *str_cache;

} cache;



/* store the "globals" of the lexer in a structure which is passed around. */
typedef struct lexer_state {
int parse_errors;
Expand All @@ -37,14 +47,22 @@ typedef struct lexer_state {

Interp *interp; /* parrot interpreter */

cache obj_cache; /* cache for all sorts of objects to save memory allocations */

} lexer_state;



/* constructor for a lexer_state object */
lexer_state *new_lexer(char * const filename);

void pirerror(lexer_state * const lexer, char const * const message, ...);

void release_resources(lexer_state *lexer);

char *dupstr(lexer_state * const lexer, char * str);
char *dupstrn(lexer_state * const lexer, char * str, size_t numchars);

#endif /* PARROT_PIR_PIRCOMPILER_H_GUARD */

/*
Expand Down

0 comments on commit fa6b002

Please sign in to comment.