split up statement parser a bit
parent
e0d625b3f1
commit
b57fcd082b
784
src/cs_gen.cc
784
src/cs_gen.cc
|
@ -1119,10 +1119,377 @@ static bool compilearg(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void compile_cmd(
|
||||||
|
GenState &gs, CsCommand *id, bool &more, int rettype, int prevargs
|
||||||
|
) {
|
||||||
|
int comtype = CsCodeCom, numargs = 0, fakeargs = 0;
|
||||||
|
bool rep = false;
|
||||||
|
auto fmt = id->get_args();
|
||||||
|
for (; !fmt.empty(); ++fmt) {
|
||||||
|
switch (*fmt) {
|
||||||
|
case 'S':
|
||||||
|
case 's':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(
|
||||||
|
gs, *fmt == 's' ? CsValCstring : CsValString,
|
||||||
|
prevargs + numargs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_str(ostd::ConstCharRange(), *fmt == 's');
|
||||||
|
fakeargs++;
|
||||||
|
} else if (fmt.size() == 1) {
|
||||||
|
int numconc = 1;
|
||||||
|
while ((numargs + numconc) < MaxArguments) {
|
||||||
|
more = compilearg(
|
||||||
|
gs, CsValCstring, prevargs + numargs + numconc
|
||||||
|
);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numconc++;
|
||||||
|
}
|
||||||
|
if (numconc > 1) {
|
||||||
|
gs.code.push(CsCodeConc | CsRetString | (numconc << 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValInt, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_int();
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValInt, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_int(CsIntMin);
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValFloat, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_float();
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValFloat, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.code.push(CsCodeDup | CsRetFloat);
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
case 't':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(
|
||||||
|
gs, *fmt == 't' ? CsValCany : CsValAny,
|
||||||
|
prevargs + numargs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_null();
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValCond, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_null();
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValCode, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
compileblock(gs);
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValIdent, prevargs + numargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
if (rep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gs.gen_ident();
|
||||||
|
fakeargs++;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
gs.gen_ident(id);
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
gs.gen_int(numargs - fakeargs);
|
||||||
|
numargs++;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
comtype = CsCodeComC;
|
||||||
|
if (more) {
|
||||||
|
while (numargs < MaxArguments) {
|
||||||
|
more = compilearg(gs, CsValCany, prevargs + numargs);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto compilecomv;
|
||||||
|
case 'V':
|
||||||
|
comtype = CsCodeComV;
|
||||||
|
if (more) {
|
||||||
|
while (numargs < MaxArguments) {
|
||||||
|
more = compilearg(gs, CsValCany, prevargs + numargs);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto compilecomv;
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
if (more && (numargs < MaxArguments)) {
|
||||||
|
int numrep = *fmt - '0' + 1;
|
||||||
|
fmt -= numrep;
|
||||||
|
rep = true;
|
||||||
|
} else {
|
||||||
|
while (numargs > MaxArguments) {
|
||||||
|
gs.code.push(CsCodePop);
|
||||||
|
--numargs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gs.code.push(comtype | cs_ret_code(rettype) | (id->get_index() << 8));
|
||||||
|
return;
|
||||||
|
compilecomv:
|
||||||
|
gs.code.push(
|
||||||
|
comtype | cs_ret_code(rettype) | (numargs << 8) | (id->get_index() << 13)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_alias(GenState &gs, CsAlias *id, bool &more, int prevargs) {
|
||||||
|
int numargs = 0;
|
||||||
|
while (numargs < MaxArguments) {
|
||||||
|
more = compilearg(gs, CsValAny, prevargs + numargs);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++numargs;
|
||||||
|
}
|
||||||
|
gs.code.push(
|
||||||
|
(id->get_index() < MaxArguments ? CsCodeCallArg : CsCodeCall)
|
||||||
|
| (numargs << 8) | (id->get_index() << 13)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_local(GenState &gs, bool &more, int prevargs) {
|
||||||
|
int numargs = 0;
|
||||||
|
if (more) {
|
||||||
|
while (numargs < MaxArguments) {
|
||||||
|
more = compilearg(gs, CsValIdent, prevargs + numargs);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (more) {
|
||||||
|
while ((more = compilearg(gs, CsValPop)));
|
||||||
|
}
|
||||||
|
gs.code.push(CsCodeLocal | (numargs << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_do(
|
||||||
|
GenState &gs, bool &more, int prevargs, int rettype, int opcode
|
||||||
|
) {
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValCode, prevargs);
|
||||||
|
}
|
||||||
|
gs.code.push((more ? opcode : CsCodeNull) | cs_ret_code(rettype));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_if(
|
||||||
|
GenState &gs, CsIdent *id, bool &more, int prevargs, int rettype
|
||||||
|
) {
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValCany, prevargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
gs.code.push(CsCodeNull | cs_ret_code(rettype));
|
||||||
|
} else {
|
||||||
|
int start1 = gs.code.size();
|
||||||
|
more = compilearg(gs, CsValCode, prevargs + 1);
|
||||||
|
if (!more) {
|
||||||
|
gs.code.push(CsCodePop);
|
||||||
|
gs.code.push(CsCodeNull | cs_ret_code(rettype));
|
||||||
|
} else {
|
||||||
|
int start2 = gs.code.size();
|
||||||
|
more = compilearg(gs, CsValCode, prevargs + 2);
|
||||||
|
ostd::Uint32 inst1 = gs.code[start1];
|
||||||
|
ostd::Uint32 op1 = inst1 & ~CsCodeRetMask;
|
||||||
|
ostd::Uint32 len1 = start2 - (start1 + 1);
|
||||||
|
if (!more) {
|
||||||
|
if (op1 == (CsCodeBlock | (len1 << 8))) {
|
||||||
|
gs.code[start1] = (len1 << 8) | CsCodeJumpB | CsCodeFlagFalse;
|
||||||
|
gs.code[start1 + 1] = CsCodeEnterResult;
|
||||||
|
gs.code[start1 + len1] = (
|
||||||
|
gs.code[start1 + len1] & ~CsCodeRetMask
|
||||||
|
) | cs_ret_code(rettype);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
compileblock(gs);
|
||||||
|
} else {
|
||||||
|
ostd::Uint32 inst2 = gs.code[start2];
|
||||||
|
ostd::Uint32 op2 = inst2 & ~CsCodeRetMask;
|
||||||
|
ostd::Uint32 len2 = gs.code.size() - (start2 + 1);
|
||||||
|
if (op2 == (CsCodeBlock | (len2 << 8))) {
|
||||||
|
if (op1 == (CsCodeBlock | (len1 << 8))) {
|
||||||
|
gs.code[start1] = ((start2 - start1) << 8)
|
||||||
|
| CsCodeJumpB | CsCodeFlagFalse;
|
||||||
|
gs.code[start1 + 1] = CsCodeEnterResult;
|
||||||
|
gs.code[start1 + len1] = (
|
||||||
|
gs.code[start1 + len1] & ~CsCodeRetMask
|
||||||
|
) | cs_ret_code(rettype);
|
||||||
|
gs.code[start2] = (len2 << 8) | CsCodeJump;
|
||||||
|
gs.code[start2 + 1] = CsCodeEnterResult;
|
||||||
|
gs.code[start2 + len2] = (
|
||||||
|
gs.code[start2 + len2] & ~CsCodeRetMask
|
||||||
|
) | cs_ret_code(rettype);
|
||||||
|
return;
|
||||||
|
} else if (op1 == (CsCodeEmpty | (len1 << 8))) {
|
||||||
|
gs.code[start1] = CsCodeNull | (inst2 & CsCodeRetMask);
|
||||||
|
gs.code[start2] = (len2 << 8) | CsCodeJumpB | CsCodeFlagTrue;
|
||||||
|
gs.code[start2 + 1] = CsCodeEnterResult;
|
||||||
|
gs.code[start2 + len2] = (
|
||||||
|
gs.code[start2 + len2] & ~CsCodeRetMask
|
||||||
|
) | cs_ret_code(rettype);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gs.code.push(CsCodeCom | cs_ret_code(rettype) | (id->get_index() << 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_and_or(
|
||||||
|
GenState &gs, CsIdent *id, bool &more, int prevargs, int rettype
|
||||||
|
) {
|
||||||
|
int numargs = 0;
|
||||||
|
if (more) {
|
||||||
|
more = compilearg(gs, CsValCond, prevargs);
|
||||||
|
}
|
||||||
|
if (!more) {
|
||||||
|
gs.code.push(
|
||||||
|
((id->get_type_raw() == CsIdAnd) ? CsCodeTrue : CsCodeFalse)
|
||||||
|
| cs_ret_code(rettype)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
numargs++;
|
||||||
|
int start = gs.code.size(), end = start;
|
||||||
|
while (numargs < MaxArguments) {
|
||||||
|
more = compilearg(gs, CsValCond, prevargs + numargs);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
if ((gs.code[end] & ~CsCodeRetMask) != (
|
||||||
|
CsCodeBlock | (ostd::Uint32(gs.code.size() - (end + 1)) << 8)
|
||||||
|
)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
end = gs.code.size();
|
||||||
|
}
|
||||||
|
if (more) {
|
||||||
|
while (numargs < MaxArguments) {
|
||||||
|
more = compilearg(gs, CsValCond, prevargs + numargs);
|
||||||
|
if (!more) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numargs++;
|
||||||
|
}
|
||||||
|
gs.code.push(
|
||||||
|
CsCodeComV | cs_ret_code(rettype) |
|
||||||
|
(numargs << 8) | (id->get_index() << 13)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ostd::Uint32 op = (id->get_type_raw() == CsIdAnd)
|
||||||
|
? (CsCodeJumpResult | CsCodeFlagFalse)
|
||||||
|
: (CsCodeJumpResult | CsCodeFlagTrue);
|
||||||
|
gs.code.push(op);
|
||||||
|
end = gs.code.size();
|
||||||
|
while ((start + 1) < end) {
|
||||||
|
ostd::Uint32 len = gs.code[start] >> 8;
|
||||||
|
gs.code[start] = ((end - (start + 1)) << 8) | op;
|
||||||
|
gs.code[start + 1] = CsCodeEnter;
|
||||||
|
gs.code[start + len] = (
|
||||||
|
gs.code[start + len] & ~CsCodeRetMask
|
||||||
|
) | cs_ret_code(rettype);
|
||||||
|
start += len + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void compilestatements(GenState &gs, int rettype, int brak, int prevargs) {
|
static void compilestatements(GenState &gs, int rettype, int brak, int prevargs) {
|
||||||
char const *line = gs.source;
|
char const *line = gs.source;
|
||||||
ostd::Box<char[]> idname;
|
ostd::Box<char[]> idname;
|
||||||
int numargs;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
skipcomments(gs.source);
|
skipcomments(gs.source);
|
||||||
idname.reset();
|
idname.reset();
|
||||||
|
@ -1201,9 +1568,9 @@ static void compilestatements(GenState &gs, int rettype, int brak, int prevargs)
|
||||||
goto endstatement;
|
goto endstatement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numargs = 0;
|
|
||||||
if (!idname) {
|
if (!idname) {
|
||||||
noid:
|
noid:
|
||||||
|
int numargs = 0;
|
||||||
while (numargs < MaxArguments) {
|
while (numargs < MaxArguments) {
|
||||||
more = compilearg(gs, CsValCany, prevargs + numargs);
|
more = compilearg(gs, CsValCany, prevargs + numargs);
|
||||||
if (!more) {
|
if (!more) {
|
||||||
|
@ -1239,353 +1606,27 @@ noid:
|
||||||
} else {
|
} else {
|
||||||
switch (id->get_type_raw()) {
|
switch (id->get_type_raw()) {
|
||||||
case CsIdAlias:
|
case CsIdAlias:
|
||||||
while (numargs < MaxArguments) {
|
compile_alias(
|
||||||
more = compilearg(gs, CsValAny, prevargs + numargs);
|
gs, static_cast<CsAlias *>(id), more, prevargs
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++numargs;
|
|
||||||
}
|
|
||||||
gs.code.push(
|
|
||||||
(id->get_index() < MaxArguments
|
|
||||||
? CsCodeCallArg
|
|
||||||
: CsCodeCall
|
|
||||||
) | (numargs << 8) | (id->get_index() << 13)
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case CsIdCommand: {
|
case CsIdCommand:
|
||||||
int comtype = CsCodeCom, fakeargs = 0;
|
compile_cmd(
|
||||||
bool rep = false;
|
gs, static_cast<CsCommand *>(id), more,
|
||||||
auto fmt = static_cast<CsCommand *>(id)->get_args();
|
rettype, prevargs
|
||||||
for (; !fmt.empty(); ++fmt) {
|
|
||||||
switch (*fmt) {
|
|
||||||
case 'S':
|
|
||||||
case 's':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, *fmt == 's'
|
|
||||||
? CsValCstring : CsValString,
|
|
||||||
prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_str(
|
|
||||||
ostd::ConstCharRange(), *fmt == 's'
|
|
||||||
);
|
|
||||||
fakeargs++;
|
|
||||||
} else if (fmt.size() == 1) {
|
|
||||||
int numconc = 1;
|
|
||||||
while ((numargs + numconc) < MaxArguments) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCstring,
|
|
||||||
prevargs + numargs + numconc
|
|
||||||
);
|
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numconc++;
|
|
||||||
}
|
|
||||||
if (numconc > 1) {
|
|
||||||
gs.code.push(
|
|
||||||
CsCodeConc | CsRetString |
|
|
||||||
(numconc << 8)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValInt, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_int();
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValInt, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_int(CsIntMin);
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValFloat, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_float();
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValFloat, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.code.push(CsCodeDup | CsRetFloat);
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
case 't':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, *fmt == 't'
|
|
||||||
? CsValCany : CsValAny,
|
|
||||||
prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_null();
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCond, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_null();
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCode, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
compileblock(gs);
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
if (more) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValIdent, prevargs + numargs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
if (rep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gs.gen_ident();
|
|
||||||
fakeargs++;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case '$':
|
|
||||||
gs.gen_ident(id);
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'N':
|
|
||||||
gs.gen_int(numargs - fakeargs);
|
|
||||||
numargs++;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
comtype = CsCodeComC;
|
|
||||||
if (more) {
|
|
||||||
while (numargs < MaxArguments) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCany, prevargs + numargs
|
|
||||||
);
|
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto compilecomv;
|
|
||||||
case 'V':
|
|
||||||
comtype = CsCodeComV;
|
|
||||||
if (more) {
|
|
||||||
while (numargs < MaxArguments) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCany, prevargs + numargs
|
|
||||||
);
|
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto compilecomv;
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
if (more && (numargs < MaxArguments)) {
|
|
||||||
int numrep = *fmt - '0' + 1;
|
|
||||||
fmt -= numrep;
|
|
||||||
rep = true;
|
|
||||||
} else {
|
|
||||||
while (numargs > MaxArguments) {
|
|
||||||
gs.code.push(CsCodePop);
|
|
||||||
--numargs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gs.code.push(
|
|
||||||
comtype | cs_ret_code(rettype) |
|
|
||||||
(id->get_index() << 8)
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
compilecomv:
|
|
||||||
gs.code.push(
|
|
||||||
comtype | cs_ret_code(rettype) | (numargs << 8) |
|
|
||||||
(id->get_index() << 13)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CsIdLocal:
|
case CsIdLocal:
|
||||||
if (more) {
|
compile_local(gs, more, prevargs);
|
||||||
while (numargs < MaxArguments) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValIdent, prevargs + numargs
|
|
||||||
);
|
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (more) {
|
|
||||||
while ((more = compilearg(gs, CsValPop)));
|
|
||||||
}
|
|
||||||
gs.code.push(CsCodeLocal | (numargs << 8));
|
|
||||||
break;
|
break;
|
||||||
case CsIdDo:
|
case CsIdDo:
|
||||||
if (more) {
|
compile_do(gs, more, prevargs, rettype, CsCodeDo);
|
||||||
more = compilearg(gs, CsValCode, prevargs);
|
|
||||||
}
|
|
||||||
gs.code.push(
|
|
||||||
(more ? CsCodeDo : CsCodeNull) | cs_ret_code(rettype)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case CsIdDoArgs:
|
case CsIdDoArgs:
|
||||||
if (more) {
|
compile_do(gs, more, prevargs, rettype, CsCodeDoArgs);
|
||||||
more = compilearg(gs, CsValCode, prevargs);
|
|
||||||
}
|
|
||||||
gs.code.push(
|
|
||||||
(more ? CsCodeDoArgs : CsCodeNull) |
|
|
||||||
cs_ret_code(rettype)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case CsIdIf:
|
case CsIdIf:
|
||||||
if (more) {
|
compile_if(gs, id, more, prevargs, rettype);
|
||||||
more = compilearg(gs, CsValCany, prevargs);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
gs.code.push(CsCodeNull | cs_ret_code(rettype));
|
|
||||||
} else {
|
|
||||||
int start1 = gs.code.size();
|
|
||||||
more = compilearg(gs, CsValCode, prevargs + 1);
|
|
||||||
if (!more) {
|
|
||||||
gs.code.push(CsCodePop);
|
|
||||||
gs.code.push(CsCodeNull | cs_ret_code(rettype));
|
|
||||||
} else {
|
|
||||||
int start2 = gs.code.size();
|
|
||||||
more = compilearg(gs, CsValCode, prevargs + 2);
|
|
||||||
ostd::Uint32 inst1 = gs.code[start1];
|
|
||||||
ostd::Uint32 op1 = inst1 & ~CsCodeRetMask;
|
|
||||||
ostd::Uint32 len1 = start2 - (start1 + 1);
|
|
||||||
if (!more) {
|
|
||||||
if (op1 == (CsCodeBlock | (len1 << 8))) {
|
|
||||||
gs.code[start1] = (len1 << 8) |
|
|
||||||
CsCodeJumpB | CsCodeFlagFalse;
|
|
||||||
gs.code[start1 + 1] = CsCodeEnterResult;
|
|
||||||
gs.code[start1 + len1] = (
|
|
||||||
gs.code[start1 + len1] & ~CsCodeRetMask
|
|
||||||
) | cs_ret_code(rettype);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
compileblock(gs);
|
|
||||||
} else {
|
|
||||||
ostd::Uint32 inst2 = gs.code[start2];
|
|
||||||
ostd::Uint32 op2 = inst2 & ~CsCodeRetMask;
|
|
||||||
ostd::Uint32 len2 = gs.code.size() - (start2 + 1);
|
|
||||||
if (op2 == (CsCodeBlock | (len2 << 8))) {
|
|
||||||
if (op1 == (CsCodeBlock | (len1 << 8))) {
|
|
||||||
gs.code[start1] = (
|
|
||||||
(start2 - start1) << 8
|
|
||||||
) | CsCodeJumpB | CsCodeFlagFalse;
|
|
||||||
gs.code[start1 + 1] = CsCodeEnterResult;
|
|
||||||
gs.code[start1 + len1] = (
|
|
||||||
gs.code[start1 + len1] & ~CsCodeRetMask
|
|
||||||
) | cs_ret_code(rettype);
|
|
||||||
gs.code[start2] = (len2 << 8) | CsCodeJump;
|
|
||||||
gs.code[start2 + 1] = CsCodeEnterResult;
|
|
||||||
gs.code[start2 + len2] = (
|
|
||||||
gs.code[start2 + len2] & ~CsCodeRetMask
|
|
||||||
) | cs_ret_code(rettype);
|
|
||||||
break;
|
|
||||||
} else if (op1 == (CsCodeEmpty | (len1 << 8))) {
|
|
||||||
gs.code[start1] = CsCodeNull |
|
|
||||||
(inst2 & CsCodeRetMask);
|
|
||||||
gs.code[start2] = (len2 << 8)
|
|
||||||
| CsCodeJumpB | CsCodeFlagTrue;
|
|
||||||
gs.code[start2 + 1] = CsCodeEnterResult;
|
|
||||||
gs.code[start2 + len2] = (
|
|
||||||
gs.code[start2 + len2] & ~CsCodeRetMask
|
|
||||||
) | cs_ret_code(rettype);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gs.code.push(
|
|
||||||
CsCodeCom | cs_ret_code(rettype) |
|
|
||||||
(id->get_index() << 8)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CsIdBreak:
|
case CsIdBreak:
|
||||||
gs.code.push(CsCodeBreak | CsCodeFlagFalse);
|
gs.code.push(CsCodeBreak | CsCodeFlagFalse);
|
||||||
|
@ -1612,71 +1653,7 @@ compilecomv:
|
||||||
break;
|
break;
|
||||||
case CsIdAnd:
|
case CsIdAnd:
|
||||||
case CsIdOr:
|
case CsIdOr:
|
||||||
if (more) {
|
compile_and_or(gs, id, more, prevargs, rettype);
|
||||||
more = compilearg(gs, CsValCond, prevargs);
|
|
||||||
}
|
|
||||||
if (!more) {
|
|
||||||
gs.code.push(
|
|
||||||
((id->get_type_raw() == CsIdAnd)
|
|
||||||
? CsCodeTrue
|
|
||||||
: CsCodeFalse
|
|
||||||
) | cs_ret_code(rettype)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
numargs++;
|
|
||||||
int start = gs.code.size(), end = start;
|
|
||||||
while (numargs < MaxArguments) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCond, prevargs + numargs
|
|
||||||
);
|
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
if ((
|
|
||||||
gs.code[end] & ~CsCodeRetMask
|
|
||||||
) != (
|
|
||||||
CsCodeBlock | (ostd::Uint32(
|
|
||||||
gs.code.size() - (end + 1)
|
|
||||||
) << 8)
|
|
||||||
)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
end = gs.code.size();
|
|
||||||
}
|
|
||||||
if (more) {
|
|
||||||
while (numargs < MaxArguments) {
|
|
||||||
more = compilearg(
|
|
||||||
gs, CsValCond, prevargs + numargs
|
|
||||||
);
|
|
||||||
if (!more) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numargs++;
|
|
||||||
}
|
|
||||||
gs.code.push(
|
|
||||||
CsCodeComV | cs_ret_code(rettype) |
|
|
||||||
(numargs << 8) | (id->get_index() << 13)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ostd::Uint32 op = (id->get_type_raw() == CsIdAnd)
|
|
||||||
? (CsCodeJumpResult | CsCodeFlagFalse)
|
|
||||||
: (CsCodeJumpResult | CsCodeFlagTrue);
|
|
||||||
gs.code.push(op);
|
|
||||||
end = gs.code.size();
|
|
||||||
while ((start + 1) < end) {
|
|
||||||
ostd::Uint32 len = gs.code[start] >> 8;
|
|
||||||
gs.code[start] = (
|
|
||||||
(end - (start + 1)) << 8
|
|
||||||
) | op;
|
|
||||||
gs.code[start + 1] = CsCodeEnter;
|
|
||||||
gs.code[start + len] = (
|
|
||||||
gs.code[start + len] & ~CsCodeRetMask
|
|
||||||
) | cs_ret_code(rettype);
|
|
||||||
start += len + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CsIdIvar:
|
case CsIdIvar:
|
||||||
if (!(more = compilearg(gs, CsValInt, prevargs))) {
|
if (!(more = compilearg(gs, CsValInt, prevargs))) {
|
||||||
|
@ -1704,6 +1681,7 @@ compilecomv:
|
||||||
if (!(more = compilearg(gs, CsValCstring, prevargs))) {
|
if (!(more = compilearg(gs, CsValCstring, prevargs))) {
|
||||||
gs.code.push(CsCodePrint | (id->get_index() << 8));
|
gs.code.push(CsCodePrint | (id->get_index() << 8));
|
||||||
} else {
|
} else {
|
||||||
|
int numargs = 0;
|
||||||
do {
|
do {
|
||||||
++numargs;
|
++numargs;
|
||||||
} while (numargs < MaxArguments && (
|
} while (numargs < MaxArguments && (
|
||||||
|
|
Loading…
Reference in New Issue