/* * does type-resolve on an IO node to transform timer inputs into appropriate actions * returns 0 to stop walk, 1 to continue */ static int guppy_timerio_typeresolve (compops_t *cops, tnode_t **nodep, typecheck_t *tc) { if ((*nodep)->tag == gup.tag_INPUT) { tnode_t *lhstype; lhstype = typecheck_gettype (tnode_nthsubof (*nodep, 0), NULL); if (lhstype && (lhstype->tag == gup.tag_TIMER)) { /* this one! */ tnode_t *rhs = tnode_nthsubof (*nodep, 1); if (rhs->tag == gup.tag_AFTER) { /* assuming timeout after expression */ tnode_t *expr = tnode_nthsubof (rhs, 0); tnode_t *type = tnode_nthsubof (rhs, 1); tnode_t *newnode = tnode_create (gup.tag_TIMERWAIT, OrgOf (*nodep), expr, type); typeresolve_subtree (&newnode, tc); *nodep = newnode; } else { /* assuming read timer */ tnode_t *type = tnode_nthsubof (*nodep, 2); /* from the input node */ tnode_t *newnode = tnode_create (gup.tag_TIMERREAD, OrgOf (*nodep), rhs, type); typeresolve_subtree (&newnode, tc); *nodep = newnode; } return 0; } } if (cops->next && tnode_hascompop_i (cops->next, (int)COPS_TYPERESOLVE)) { return tnode_callcompop_i (cops->next, (int)COPS_TYPERESOLVE, 2, nodep, tc); } return 1; }
/* * this goes through a trace and removes trailing "Skip"s, or turns trailing ends into fixpoint loops * returns 0 on success, non-zero on failure */ int traceslang_noskiporloop (tnode_t **exprp) { traceslang_erefset_t *tailrefs = traceslang_lastactionsp (exprp); tnode_t *fixname; int i, fixcount = 0; fixname = tnode_create (traceslang.tag_NFIX, NULL, NULL); #if 0 fprintf (stderr, "traceslang_noskiporloop(): transforming:\n"); tnode_dumptree (*exprp, 1, stderr); fprintf (stderr, "traceslang_noskiporloop(): with tail references:\n"); traceslang_dumprefset (tailrefs, 1, stderr); #endif for (i=0; i<DA_CUR (tailrefs->events); i++) { tnode_t **eventp = DA_NTHITEM (tailrefs->events, i); tnode_t *ev = *eventp; if (ev->tag == traceslang.tag_SKIP) { /* remove from traces */ *eventp = NULL; tnode_free (ev); } else if (ev->tag == traceslang.tag_NPARAM) { /* trailing event, sequential with fixpoint instance */ tnode_t *ilist = parser_buildlistnode (NULL, ev, fixname, NULL); *eventp = tnode_createfrom (traceslang.tag_SEQ, ev, ilist); fixcount++; } } if (fixcount) { char *rfixname = (char *)smalloc (64); name_t *sfixname; tnode_t *fixnode; sprintf (rfixname, "FP%d", anonidcounter++); sfixname = name_addname (rfixname, NULL, tnode_create (traceslang.tag_FIXPOINTTYPE, NULL), fixname); sfree (rfixname); tnode_setnthname (fixname, 0, sfixname); fixnode = tnode_createfrom (traceslang.tag_FIXPOINT, *exprp, fixname, *exprp); SetNameDecl (sfixname, fixnode); *exprp = fixnode; } traceslang_freerefset (tailrefs); #if 0 fprintf (stderr, "traceslang_noskiporloop(): into:\n"); tnode_dumptree (*exprp, 1, stderr); #endif return 0; }
TreeNode* tnode_add_child(TreeNode* tnode, void* var, void (*destroy_var) (void *)) { if (tnode->child == NULL) { tnode->child = tnode_create(var, destroy_var); return tnode->child; } else { TreeNode* it = tnode->child; while (it->next != NULL) it = it->next; it->next = tnode_create(var, destroy_var); return it->next; } }
/* * reduces a primitive process */ static void guppy_reduce_primproc (dfastate_t *dfast, parsepriv_t *pp, void *rarg) { token_t *tok; ntdef_t *tag; tok = parser_gettok (pp); if (tok->type == KEYWORD) { char *ustr = string_upper (tok->u.kw->name); tag = tnode_lookupnodetag (ustr); sfree (ustr); if (!tag) { parser_error (SLOCN (pp->lf), "unknown primitive process [%s] in guppy_reduce_primproc()", tok->u.kw->name); goto out_error; } } else { parser_error (SLOCN (pp->lf), "unknown primitive process in guppy_reduce_primproc()"); goto out_error; } *(dfast->ptr) = tnode_create (tag, SLOCN (tok->origin)); out_error: lexer_freetoken (tok); return; }
/* * creates a new constant-node */ tnode_t *constprop_newconst (consttype_e ctype, tnode_t *orig, tnode_t *type, ...) { va_list ap; tnode_t *cnode; consthook_t *ch = cprop_newconsthook (); va_start (ap, type); ch->type = ctype; ch->orig = orig; switch (ctype) { case CONST_INVALID: break; case CONST_BYTE: ch->u.bval = (unsigned char)va_arg (ap, int); break; case CONST_BOOL: case CONST_INT: ch->u.ival = va_arg (ap, int64_t); break; case CONST_DOUBLE: ch->u.dval = va_arg (ap, double); break; case CONST_ULL: ch->u.ullval = va_arg (ap, unsigned long long); break; } va_end (ap); cnode = tnode_create (tag_CONST, NULL, type, ch); return cnode; }
/* * does a structure copy on a traceslang tree -- duplicates structural nodes, but leaves others intact * returns new tree on success, NULL on failure */ tnode_t *traceslang_structurecopy (tnode_t *expr) { tnode_t *newtree; traceslang_eset_t *fixset; /* extract a list of fixpoint names from what we're about to duplicate */ fixset = traceslang_allfixpoints (expr); newtree = tnode_copyoraliastree (expr, trlang_structurecopyfcn); if (DA_CUR (fixset->events)) { int i; traceslang_eset_t *newset = traceslang_newset (); /* got some fixpoint names here, duplicate them into a new set of NFIXs */ for (i=0; i<DA_CUR (fixset->events); i++) { char *rfixname = (char *)smalloc (64); name_t *sfixname; tnode_t *fixname; /* create fresh name */ fixname = tnode_create (traceslang.tag_NFIX, NULL, NULL); sprintf (rfixname, "FP%d", anonidcounter++); sfixname = name_addname (rfixname, NULL, tnode_create (traceslang.tag_FIXPOINTTYPE, NULL), fixname); sfree (rfixname); tnode_setnthname (fixname, 0, sfixname); /* add to substitution lists */ dynarray_add (newset->events, fixname); } newtree = treeops_substitute (newtree, DA_PTR (fixset->events), DA_PTR (newset->events), DA_CUR (fixset->events)); traceslang_freeset (newset); } traceslang_freeset (fixset); return newtree; }
/* * called to invert traces (in pre-walk order) * returns 0 to stop walk, 1 to continue */ static int traceslang_invert_prewalk (tnode_t *node, void *arg) { tnode_t **resp = (tnode_t **)arg; #if 1 fprintf (stderr, "traceslang_invert_prewalk(): here! node type is [%s]\n", node->tag->name); #endif if (parser_islistnode (node)) { /*{{{ list, build new list containing copies*/ tnode_t *newlist = parser_newlistnode (NULL); int nitems, i; tnode_t **items = parser_getlistitems (node, &nitems); for (i=0; i<nitems; i++) { tnode_t *nitm = traceslang_invert (items[i]); parser_addtolist (newlist, nitm); } *resp = newlist; return 0; /*}}}*/ } else if (node->tag == traceslang.tag_INPUT) { /*{{{ input, turn into output*/ tnode_t *newnode; tnode_t *lhs = tnode_nthsubof (node, 0); tnode_t *tag = tnode_nthsubof (node, 1); tnode_t *newlhs = lhs ? traceslang_invert (lhs) : NULL; tnode_t *newtag = tag ? traceslang_invert (tag) : NULL; newnode = tnode_create (traceslang.tag_OUTPUT, NULL, newlhs, newtag); *resp = newnode; return 0; /*}}}*/ } else if (node->tag == traceslang.tag_OUTPUT) { /*{{{ output, turn into input*/ tnode_t *newnode; tnode_t *lhs = tnode_nthsubof (node, 0); tnode_t *tag = tnode_nthsubof (node, 1); tnode_t *newlhs = lhs ? traceslang_invert (lhs) : NULL; tnode_t *newtag = tag ? traceslang_invert (tag) : NULL; newnode = tnode_create (traceslang.tag_INPUT, NULL, newlhs, newtag); *resp = newnode; return 0; /*}}}*/ } else if (node->tag == traceslang.tag_DET) { /*{{{ det, turn into ndet*/ tnode_t *newnode; tnode_t *ilist = tnode_nthsubof (node, 0); tnode_t *newlist = ilist ? traceslang_invert (ilist) : NULL; newnode = tnode_create (traceslang.tag_NDET, NULL, newlist); *resp = newnode; return 0; /*}}}*/ } else if ((node->tag == traceslang.tag_NDET) || (node->tag == traceslang.tag_SEQ) || (node->tag == traceslang.tag_PAR)) { /*{{{ ndet, seq or par (setnode), leave alone*/ tnode_t *newnode; tnode_t *ilist = tnode_nthsubof (node, 0); tnode_t *newlist = ilist ? traceslang_invert (ilist) : NULL; newnode = tnode_create (node->tag, NULL, newlist); *resp = newnode; return 0; /*}}}*/ } else { /*{{{ default: return node exactly*/ *resp = node; return 0; /*}}}*/ } return 1; }