Join memory during undefinition

This commit is contained in:
Devine Lu Linvega 2024-05-21 10:36:14 -07:00
parent fc903be471
commit ff0c53cf68
3 changed files with 55 additions and 10 deletions

19
examples/rules.modal Normal file
View File

@ -0,0 +1,19 @@
<> rule0 data
<> rule1 data-1
<> rule2
<> rule3 data-10
<> rule4 data-100
?(?-) (Undefine an empty rule)
>< rule2
?(?-) (Undefine the last rule)
>< rule4
?(?-) (Undefine a non-existant rule)
>< rule5
a sample program

View File

@ -10,7 +10,7 @@ dest:
run: all bin/modal run: all bin/modal
@ bin/modal -q examples/hello.modal @ bin/modal -q examples/hello.modal
debug: all bin/modal-debug debug: all bin/modal-debug
@ bin/modal-debug examples/hello.modal @ bin/modal-debug examples/rules.modal
test: all bin/modal-debug bin/modal test: all bin/modal-debug bin/modal
@ bin/modal -v @ bin/modal -v
@ bin/modal-debug -q examples/fizzbuzz.modal @ bin/modal-debug -q examples/fizzbuzz.modal

View File

@ -22,6 +22,15 @@ copy(char *src, char *dst, int length)
return dst; return dst;
} }
static int
slen(char *s)
{
char *cap = s;
while(*cap++)
;
return cap - s;
}
static char * static char *
walk(char *s) walk(char *s)
{ {
@ -233,10 +242,10 @@ parse_frag(char **side, char *s)
{ {
char c, *cap; char c, *cap;
while((c = *s) && c == ' ') s++; while((c = *s) && c == ' ') s++;
if(c == ')') { if(c == ')' || (c == '<' && s[1] == '>') || (c == '>' && s[1] == '<')) {
*side = NULL; *side = NULL;
return s; return s;
} else if((c == '<' && s[1] == '>') || (c == '>' && s[1] == '<') || (c == '(' && s[1] == ')')) { } else if((c == '(' && s[1] == ')')) {
*side = NULL; *side = NULL;
return s + 2; return s + 2;
} else { } else {
@ -257,7 +266,6 @@ find_rule(char *s, char *cap)
if(*s == '(') s++, cap--; if(*s == '(') s++, cap--;
while(r < rules_) { while(r < rules_) {
char *ss = s, *a = r->a; char *ss = s, *a = r->a;
if(a)
while(*ss++ == *a++) while(*ss++ == *a++)
if(!*a && ss == cap) return r; if(!*a && ss == cap) return r;
r++; r++;
@ -265,6 +273,24 @@ find_rule(char *s, char *cap)
return NULL; return NULL;
} }
static void
remove_rule(Rule *r)
{
if(r < rules_ - 1) {
int distance = slen(r->a) + (r->b != NULL ? slen(r->b) : 0);
char *memsrc = (r + 1)->a;
copy(memsrc, r->a, dict_ - memsrc);
while(r < rules_ - 1) {
Rule *next = r + 1;
r->id = next->id, r->refs = next->refs;
r->a = next->a - distance;
r->b = next->b == NULL ? NULL : next->b - distance;
r++;
}
}
rules_--;
}
static int static int
rewrite(void) rewrite(void)
{ {
@ -272,7 +298,7 @@ rewrite(void)
while(*s == ' ') s++; while(*s == ' ') s++;
while((c = *s)) { while((c = *s)) {
if(c == '(' || spacer(last)) { if(c == '(' || spacer(last)) {
Rule *r = NULL; Rule *r;
/* phase: undefine */ /* phase: undefine */
if(c == '>' && s[1] == '<') { if(c == '>' && s[1] == '<') {
s += 2; s += 2;
@ -280,7 +306,7 @@ rewrite(void)
cap = walk(s), r = find_rule(s, cap); cap = walk(s), r = find_rule(s, cap);
if(r != NULL) { if(r != NULL) {
if(!quiet) fprintf(stderr, ">< (%s) (%s)\n", r->a ? r->a : "", r->b ? r->b : ""); if(!quiet) fprintf(stderr, ">< (%s) (%s)\n", r->a ? r->a : "", r->b ? r->b : "");
r->a = 0; remove_rule(r);
} }
while(*cap == ' ') cap++; while(*cap == ' ') cap++;
return write_tail(cap); return write_tail(cap);
@ -310,7 +336,7 @@ rewrite(void)
} }
/* phase: match */ /* phase: match */
for(r = rules; r < rules_; r++) for(r = rules; r < rules_; r++)
if(r->a != NULL && apply_rule(r, s)) return 1; if(apply_rule(r, s)) return 1;
} }
*dst_++ = last = c, s++; *dst_++ = last = c, s++;
} }
@ -326,7 +352,7 @@ main(int argc, char **argv)
return !printf("usage: modal [-vqn] source.modal\n"); return !printf("usage: modal [-vqn] source.modal\n");
for(i = 1; i < argc && *argv[i] == '-'; i++) { for(i = 1; i < argc && *argv[i] == '-'; i++) {
switch(argv[i][1]) { switch(argv[i][1]) {
case 'v': /* version */ return !printf("Modal Interpreter, 17 May 2024.\n"); case 'v': /* version */ return !printf("Modal Interpreter, 21 May 2024.\n");
case 'q': /* quiet */ quiet = 1; break; case 'q': /* quiet */ quiet = 1; break;
case 'p': /* debug */ debug = 1; break; case 'p': /* debug */ debug = 1; break;
case 'a': /* access */ access = 1; break; case 'a': /* access */ access = 1; break;