SemVal *p_catCode(SemVal *lval, SemVal *rval) { register unsigned l; register unsigned r; r = rval->codelen; /* sizeof rval code */ l = lval->codelen; /* sizeof lval code */ lval->code = rss_realloc(lval->code, /* room for new code */ (l + r) * sizeof(int8_t)); /* catenate the code */ memcpy(lval->code + l, rval->code, r * sizeof(int8_t)); lval->codelen += r; /* new size */ patchadd(l, &lval->truelist, &lval->truelen, rval->truelist, rval->truelen); patchadd(l, &lval->falselist, &lval->falselen, rval->falselist, rval->falselen); patchadd(l, &lval->continuelist, &lval->continuelen, rval->continuelist, rval->continuelen); lval->type |= rval->type; /* type of combined code */ /* (is ok with same types) */ p_discard(rval); /* free memory used by SemVal */ return (lval); /* return new frame */ }
SemVal *p_ternary(SemVal *cond, SemVal *ifTrue, SemVal *ifFalse) { if ((ifTrue->type & ifFalse->type & e_typeMask) == 0) { util_semantic(gp_typeConflict, "?:"); p_clearOperands(ifTrue, ifFalse); return cond; } if (test_type(cond, e_const)) /* constant: true or false */ { p_discard(cond); if (cond->evalue) { p_discard(ifFalse); p_expr2stack(ifTrue); return ifTrue; } p_discard(ifTrue); p_expr2stack(ifFalse); return ifFalse; } p_expr2stack(ifTrue); /* convert the expressions to code */ p_expr2stack(ifFalse); p_generateCode(cond, op_jmp_false, j_falselist); /* jmp around the ifTrue code */ p_patchupTrue(cond, 1); /* destination for the ifTrue code */ p_catCode(cond, ifTrue); /* cond = cond + ifTrue */ p_generateCode(cond, op_jmp, j_truelist); /* jmp around the ifFalse code */ p_patchupFalse(cond, 1); /* destination of the false alternative */ p_catCode(cond, ifFalse); /* cond = cond + ifTrue + jmp + ifFalse */ p_patchupTrue(cond, 1); /* jump from ifTrue to the end of expr. */ return cond; /* ?: return */ }
/* opstr is '=', or "/=", etc. */ SemVal *p_assignment(SemVal *lval, SemVal *rval, char *opstr) { SemVal *tmp; unsigned type; unsigned value; if (!test_type(lval, e_var)) { util_semantic(gp_lvalueNeeded, opstr); p_discard(rval); return lval; } p_trySIconvert(lval, rval); p_expr2stack(rval); /* convert rval to code */ /* same types */ if (lval->type & rval->type & (e_int | e_str | e_list)) { type = lval->type; /* save type/idx for return */ value = lval->evalue; p_generateCode(lval, op_copy_var, lval->evalue); tmp = p_catCode(rval, lval); /* catenate p_assignment code */ tmp->evalue = value; /* set lvalue type and idx */ tmp->type = type; return tmp; } util_semantic(gp_typeConflict, opstr); p_discard(rval); return lval; }
SemVal *p_catStmnts(SemVal *lval, SemVal *rval) { p_patchupFalse(lval, 1); msg("lval length: %u, rval length: %u", lval->codelen, rval->codelen); if (gp_nestLevel == 0) { util_out(gp_bin, lval->code, lval->codelen); p_discard(lval); return rval; } return p_catCode(lval, rval); }
SemVal *p_indexOp(SemVal *larg, SemVal *rarg) { register int ok; ExprType type = f_element; SemVal *tmp; p_expr2stack(larg); /* arg to stack */ p_expr2stack(rarg); /* arg to stack */ /* This follows the code of `p_twoArgs.c' to compute a list/string */ /* element */ /* first arg must be int */ if (!test_type(larg, e_int)) /* first expression is no int */ { tmp = larg; /* then swap */ larg = rarg; rarg = tmp; } if ( (ok = test_type(larg, e_int)) ) /* right arg must be int */ { /* second arg == list: ok */ if (!(ok = test_type(rarg, e_list))) { /* second arg == string: ok */ ok = test_type(rarg, e_str); type = f_str_el; /* string element requested */ } } if (ok) { p_catCode(rarg, larg); /* make one code vector */ p_callRss(rarg, type); } else { util_semantic(gp_typeConflict, gp_funstring[type]); p_discard(larg); } return (rarg); }
SemVal *p_twoArgs(ExprType type, SemVal *larg, SemVal *rarg) { register int ok; msg("start"); p_expr2stack(larg); /* arg to stack */ p_expr2stack(rarg); /* arg to stack */ switch ((FunNr)type) { case f_fgets: ok = test_type(larg, e_str) && test_type(rarg, e_list); break; case f_element: /* f_element */ /* first arg must be int */ if ( (ok = test_type(larg, e_int)) ) { /* second arg == list: ok */ if (!(ok = test_type(rarg, e_list))) { /* second arg == string: ok */ ok = test_type(rarg, e_str); type = f_str_el; /* string element requested */ } } break; case f_resize: ok = test_type(larg, e_str) && test_type(rarg, e_int); break; case f_listfind: ok = test_type(larg, e_list) && test_type(rarg, e_str); break; case f_listunion: ok = test_type(larg, e_list) && test_type(rarg, e_str | e_list); break; default: /* case f_strchr: case f_strtok: case f_c_ext: case f_c_base: case f_c_path: case f_strfind: */ ok = larg->type & rarg->type & e_str; } msg("types test %d, funstring: %x", ok, type); if (ok) { p_catCode(rarg, larg); /* make one code vector */ p_callRss(rarg, type); } else { util_semantic(gp_typeConflict, gp_funstring[type]); p_discard(larg); rarg = p_stackFrame(e_null); } msg("leaving"); return rarg; }