1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-07-20 13:28:56 +00:00

More robust stack depth checking and var parsing

This commit is contained in:
David Schmenk 2017-12-24 20:35:39 -08:00
parent 70ba7d0e0e
commit 7843bc41ce
5 changed files with 774 additions and 619 deletions

View File

@ -623,42 +623,15 @@ def emit_pending_seq#0
if not pending_seq; return; fin
lcl_pending = pending_seq
pending_seq = NULL
//if outflags & OPTIMIZE
// while crunch_seq(@lcl_pending, 0); loop
// while crunch_seq(@lcl_pending, 1); loop
//fin
if outflags & OPTIMIZE
while crunch_seq(@lcl_pending, 0); loop
if outflags & OPTIMIZE2
while crunch_seq(@lcl_pending, 1); loop
fin
fin
while lcl_pending
op = lcl_pending
when op->code
is NEG_CODE
is COMP_CODE
is LOGIC_NOT_CODE
is INC_CODE
is DEC_CODE
is BPTR_CODE
is WPTR_CODE
emit_unaryop(op->code)
break
is MUL_CODE
is DIV_CODE
is MOD_CODE
is ADD_CODE
is SUB_CODE
is SHL_CODE
is SHR_CODE
is AND_CODE
is OR_CODE
is EOR_CODE
is EQ_CODE
is NE_CODE
is GE_CODE
is LT_CODE
is GT_CODE
is LE_CODE
is LOGIC_OR_CODE
is LOGIC_AND_CODE
emit_op(op->code)
break
is CONST_CODE
emit_const(op=>val)
break
@ -755,6 +728,63 @@ def emit_pending_seq#0
is CODETAG_CODE
printf("_B%03d%c\n", op->tag, LBL);
break;
is NEG_CODE
is COMP_CODE
is LOGIC_NOT_CODE
is INC_CODE
is DEC_CODE
is BPTR_CODE
is WPTR_CODE
emit_unaryop(op->code)
break
is MUL_CODE
is DIV_CODE
is MOD_CODE
is ADD_CODE
is SUB_CODE
is SHL_CODE
is SHR_CODE
is AND_CODE
is OR_CODE
is EOR_CODE
is EQ_CODE
is NE_CODE
is GE_CODE
is LT_CODE
is GT_CODE
is LE_CODE
is LOGIC_OR_CODE
is LOGIC_AND_CODE
emit_op(op->code)
break
is MUL_CODE
is DIV_CODE
is MOD_CODE
is ADD_CODE
is SUB_CODE
is SHL_CODE
is SHR_CODE
is AND_CODE
is OR_CODE
is EOR_CODE
is EQ_CODE
is NE_CODE
is GE_CODE
is LT_CODE
is GT_CODE
is LE_CODE
is LOGIC_OR_CODE
is LOGIC_AND_CODE
emit_op(op->code)
break
is NEG_CODE
is COMP_CODE
is LOGIC_NOT_CODE
is INC_CODE
is DEC_CODE
is BPTR_CODE
is WPTR_CODE
emit_unaryop(op->code)
is NOP_CODE
break
otherwise
@ -774,10 +804,10 @@ end
def emit_seq(seq)#0
word op
byte string
string = 0
string = FALSE
op = seq
while op
if op->code == STR_CODE; string = 1; fin
if op->code == STR_CODE; string = TRUE; break; fin
op = op=>nextop
loop
pending_seq = cat_seq(pending_seq, seq)
@ -788,6 +818,6 @@ def emit_seq(seq)#0
//
// We must also force output if the sequence includes a CS opcode, as the
// associated 'constant' is only temporarily valid.
if !(outflags & OPTIMIZE) or (outflags & NO_COMBINE) or string
if !(outflags & (OPTIMIZE|OPTIMIZE2)) or (outflags & NO_COMBINE) or string
emit_pending_seq
end

View File

@ -505,12 +505,8 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth)
cfnparms = 0; cfnvals = 1;
type &= ~FUNC_TYPE;
}
//while ((idxseq = parse_expr(NULL, stackdepth)))
while ((valseq = parse_expr(valseq, stackdepth)) && scantoken == COMMA_TOKEN)
{
// valseq = cat_seq(valseq, idxseq);
// if (scantoken != COMMA_TOKEN)
// break;
valseq = gen_idxw(valseq);
valseq = gen_lw(valseq);
}
@ -794,8 +790,13 @@ int parse_stmnt(void)
switch (scantoken)
{
case IF_TOKEN:
if (!(seq = parse_expr(NULL, NULL)))
if (!(seq = parse_expr(NULL, &cfnvals)))
parse_error("Bad expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
tag_else = tag_new(BRANCH_TYPE);
tag_endif = tag_new(BRANCH_TYPE);
seq = gen_brfls(seq, tag_else);
@ -807,8 +808,13 @@ int parse_stmnt(void)
break;
emit_brnch(tag_endif);
emit_codetag(tag_else);
if (!(seq = parse_expr(NULL, NULL)))
if (!(seq = parse_expr(NULL, &cfnvals)))
parse_error("Bad expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
tag_else = tag_new(BRANCH_TYPE);
seq = gen_brfls(seq, tag_else);
emit_seq(seq);
@ -837,11 +843,16 @@ int parse_stmnt(void)
tag_prevbrk = break_tag;
break_tag = tag_wend;
emit_codetag(tag_while);
if (!(seq = parse_expr(NULL, NULL)))
if (!(seq = parse_expr(NULL, &cfnvals)))
parse_error("Bad expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
seq = gen_brfls(seq, tag_wend);
emit_seq(seq);
while (parse_stmnt()) next_line();
while (parse_stmnt()) next_line();
if (scantoken != LOOP_TOKEN)
parse_error("Missing WHILE/END");
emit_brnch(tag_while);
@ -862,8 +873,13 @@ int parse_stmnt(void)
parse_error("Missing REPEAT/UNTIL");
emit_codetag(cont_tag);
cont_tag = tag_prevcnt;
if (!(seq = parse_expr(NULL, NULL)))
if (!(seq = parse_expr(NULL, &cfnvals)))
parse_error("Bad expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
seq = gen_brfls(seq, tag_repeat);
emit_seq(seq);
emit_codetag(break_tag);
@ -882,8 +898,13 @@ int parse_stmnt(void)
addr = id_tag(tokenstr, tokenlen);
if (scan() != SET_TOKEN)
parse_error("Missing FOR =");
if (!emit_seq(parse_expr(NULL, NULL)))
if (!emit_seq(parse_expr(NULL, &cfnvals)))
parse_error("Bad FOR expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
emit_codetag(tag_for);
if (type & LOCAL_TYPE)
type & BYTE_TYPE ? emit_dlb(addr) : emit_dlw(addr);
@ -895,13 +916,23 @@ int parse_stmnt(void)
step = -1;
else
parse_error("Missing FOR TO");
if (!emit_seq(parse_expr(NULL, NULL)))
if (!emit_seq(parse_expr(NULL, &cfnvals)))
parse_error("Bad FOR TO expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
step > 0 ? emit_brgt(break_tag) : emit_brlt(break_tag);
if (scantoken == STEP_TOKEN)
{
if (!emit_seq(parse_expr(NULL, NULL)))
if (!emit_seq(parse_expr(NULL, &cfnvals)))
parse_error("Bad FOR STEP expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
emit_op(step > 0 ? ADD_TOKEN : SUB_TOKEN);
}
else
@ -922,15 +953,25 @@ int parse_stmnt(void)
break_tag = tag_new(BRANCH_TYPE);
tag_choice = tag_new(BRANCH_TYPE);
tag_of = tag_new(BRANCH_TYPE);
if (!emit_seq(parse_expr(NULL, NULL)))
if (!emit_seq(parse_expr(NULL, &cfnvals)))
parse_error("Bad CASE expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
next_line();
while (scantoken != ENDCASE_TOKEN)
{
if (scantoken == OF_TOKEN)
{
if (!emit_seq(parse_expr(NULL, NULL)))
if (!emit_seq(parse_expr(NULL, &cfnvals)))
parse_error("Bad CASE OF expression");
if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
emit_brne(tag_choice);
emit_codetag(tag_of);
while (parse_stmnt()) next_line();
@ -961,18 +1002,18 @@ int parse_stmnt(void)
break_tag = tag_prevbrk;
stack_loop--;
break;
case CONTINUE_TOKEN:
if (cont_tag)
emit_brnch(cont_tag);
else
parse_error("CONTINUE without loop");
break;
case BREAK_TOKEN:
if (break_tag)
emit_brnch(break_tag);
else
parse_error("BREAK without loop");
break;
case CONTINUE_TOKEN:
if (cont_tag)
emit_brnch(cont_tag);
else
parse_error("CONTINUE without loop");
break;
case RETURN_TOKEN:
if (infunc)
{
@ -993,13 +1034,17 @@ int parse_stmnt(void)
}
else
{
if (!emit_seq(parse_expr(NULL, NULL)))
if (!emit_seq(parse_expr(NULL, &cfnvals)))
emit_const(0);
else if (cfnvals > 1)
{
parse_warn("Expression value overflow");
while (cfnvals-- > 1) seq = gen_drop(seq);
}
emit_ret();
}
break;
case EOL_TOKEN:
//case COMMENT_TOKEN:
return (1);
case ELSE_TOKEN:
case ELSEIF_TOKEN:
@ -1027,8 +1072,7 @@ int parse_stmnt(void)
{
emit_seq(rseq);
emit_unaryop(scantoken);
tokenstr = idptr;
scan_rewind(tokenstr);
scan_rewind(idptr);
emit_seq(parse_value(NULL, LVALUE, NULL));
}
else if (scantoken != SET_TOKEN)
@ -1051,22 +1095,14 @@ int parse_stmnt(void)
}
return (scan() == EOL_TOKEN);
}
int parse_var(int type)
int parse_var(int type, long basesize)
{
char *idstr;
long constval;
int consttype, constsize, arraysize, idlen = 0;
long size = 1;
int consttype, constsize, arraysize, idlen = 0;
if (scan() == OPEN_BRACKET_TOKEN)
{
size = 0;
parse_constexpr(&size, &constsize);
if (scantoken != CLOSE_BRACKET_TOKEN)
parse_error("Missing closing bracket");
scan();
}
if (scantoken == ID_TOKEN)
if (scan() == ID_TOKEN)
{
idstr = tokenstr;
idlen = tokenlen;
@ -1079,8 +1115,7 @@ int parse_var(int type)
scan();
}
}
if (type & WORD_TYPE)
size *= 2;
size *= basesize;
if (scantoken == SET_TOKEN)
{
if (type & (EXTERN_TYPE | LOCAL_TYPE))
@ -1138,7 +1173,8 @@ int parse_struc(void)
parse_error("Missing closing bracket");
scan();
}
do {
do
{
idlen = 0;
if (scantoken == ID_TOKEN)
{
@ -1163,9 +1199,8 @@ int parse_struc(void)
if (struclen)
idconst_add(strucid, struclen, offset);
if (scantoken != END_TOKEN)
return (0);
parse_error("Missing STRUC/END");
scan();
return (1);
}
int parse_vars(int type)
{
@ -1178,7 +1213,7 @@ int parse_vars(int type)
{
case SYSFLAGS_TOKEN:
if (type & (EXTERN_TYPE | LOCAL_TYPE))
parse_error("sysflags must be global");
parse_error("SYSFLAGS must be global");
if (!parse_constexpr(&value, &size))
parse_error("Bad constant");
emit_sysflags(value);
@ -1195,8 +1230,7 @@ int parse_vars(int type)
idconst_add(idstr, idlen, value);
break;
case STRUC_TOKEN:
if (!parse_struc())
parse_error("Bad structure definition");
parse_struc();
break;
case EXPORT_TOKEN:
if (type & (EXTERN_TYPE | LOCAL_TYPE))
@ -1217,86 +1251,63 @@ int parse_vars(int type)
*/
case BYTE_TOKEN:
case WORD_TOKEN:
type |= (scantoken == BYTE_TOKEN) ? BYTE_TYPE : WORD_TYPE;
if (!parse_var(type))
return (0);
while (scantoken == COMMA_TOKEN)
type |= (scantoken == BYTE_TOKEN) ? BYTE_TYPE : WORD_TYPE;
cfnvals = 1; // Just co-opt a long variable for this case
if (scan() == OPEN_BRACKET_TOKEN)
{
if (!parse_var(type))
return (0);
//
// Get base size for variables
//
cfnvals = 0;
parse_constexpr(&cfnvals, &size);
if (scantoken != CLOSE_BRACKET_TOKEN)
parse_error("Missing closing bracket");
}
else
scan_rewind(tokenstr);
if (type & WORD_TYPE)
cfnvals *= 2;
do parse_var(type, cfnvals); while (scantoken == COMMA_TOKEN);
break;
case PREDEF_TOKEN:
/*
* Pre definition.
*/
if (scan() == ID_TOKEN)
do
{
type |= PREDEF_TYPE;
idstr = tokenstr;
idlen = tokenlen;
cfnparms = 0;
cfnvals = 1; // Default to one return value for compatibility
if (scan() == OPEN_PAREN_TOKEN)
if (scan() == ID_TOKEN)
{
do
type = (type & ~FUNC_PARMVALS) | PREDEF_TYPE;
idstr = tokenstr;
idlen = tokenlen;
cfnparms = 0;
cfnvals = 1; // Default to one return value for compatibility
if (scan() == OPEN_PAREN_TOKEN)
{
if (scan() == ID_TOKEN)
do
{
cfnparms++;
scan();
}
} while (scantoken == COMMA_TOKEN);
if (scantoken != CLOSE_PAREN_TOKEN)
parse_error("Bad function parameter list");
scan();
}
if (scantoken == POUND_TOKEN)
{
if (!parse_const(&cfnvals))
parse_error("Invalid def return value count");
scan();
}
type |= funcparms_type(cfnparms) | funcvals_type(cfnvals);
idfunc_add(idstr, idlen, type, tag_new(type));
while (scantoken == COMMA_TOKEN)
{
if (scan() == ID_TOKEN)
{
idstr = tokenstr;
idlen = tokenlen;
type &= ~FUNC_PARMVALS;
cfnparms = 0;
cfnvals = 1; // Default to one return value for compatibility
if (scan() == OPEN_PAREN_TOKEN)
{
do
if (scan() == ID_TOKEN)
{
if (scan() == ID_TOKEN)
{
cfnparms++;
scan();
}
} while (scantoken == COMMA_TOKEN);
if (scantoken != CLOSE_PAREN_TOKEN)
parse_error("Bad function parameter list");
scan();
}
if (scantoken == POUND_TOKEN)
{
if (!parse_const(&cfnvals))
parse_error("Invalid def return value count");
scan();
}
type |= funcparms_type(cfnparms) | funcvals_type(cfnvals);
idfunc_add(idstr, idlen, type, tag_new(type));
cfnparms++;
scan();
}
} while (scantoken == COMMA_TOKEN);
if (scantoken != CLOSE_PAREN_TOKEN)
parse_error("Bad function parameter list");
scan();
}
else
parse_error("Bad function pre-declaration");
if (scantoken == POUND_TOKEN)
{
if (!parse_const(&cfnvals))
parse_error("Invalid def return value count");
scan();
}
type |= funcparms_type(cfnparms) | funcvals_type(cfnvals);
idfunc_add(idstr, idlen, type, tag_new(type));
}
}
else
parse_error("Bad function pre-declaration");
else
parse_error("Bad function pre-declaration");
} while (scantoken == COMMA_TOKEN);
case EOL_TOKEN:
break;
default:
@ -1315,7 +1326,7 @@ int parse_mods(void)
while (parse_vars(EXTERN_TYPE)) next_line();
if (scantoken != END_TOKEN)
parse_error("Missing END");
return (scan() == EOL_TOKEN);
scan();
}
if (scantoken == EOL_TOKEN)
return (1);
@ -1326,7 +1337,6 @@ int parse_lambda(void)
{
int func_tag;
int cfnparms;
char *expr;
if (!infunc)
parse_error("Lambda functions only allowed inside definitions");
@ -1351,7 +1361,6 @@ int parse_lambda(void)
}
else
parse_error("Missing parameter list in lambda function");
expr = scanpos;
if (scan_lookahead() == OPEN_PAREN_TOKEN)
{
/*

File diff suppressed because it is too large Load Diff

View File

@ -272,17 +272,24 @@ byte no_ctag_offst[] = "CODE OFFSET NOT SUPPORTED"
byte no_close_paren[] = "MISSING CLOSING PAREN"
byte no_close_bracket[] = "MISSING CLOSING BRACKET"
byte missing_op[] = "MISSING OPERAND"
byte no_fin[] = "MISSING FIN"
byte no_loop[] = "MISSING LOOP"
byte no_until[] = "MISSING UNTIL"
byte no_done[] = "MISSING DONE"
byte no_local_init[] = "NO INITIALIZED LOCALS"
//
// Compiler optimizer flags
//
const OPTIMIZE = 1
const OPTIMIZE2 = 2
const NO_COMBINE = 4
byte outflags
//
// ProDOS/SOS file references
//
byte refnum, srcref, incref
byte[32] srcfile
byte[32] incfile
byte[32] relfile
word parsefile // Pointer to current file
word sysincbuf // System I/O buffer for include files
word srcline // Saved source line number
@ -293,6 +300,7 @@ byte[128] strconst
byte infunc = 0
byte stack_loop = 0
byte prevstmnt = 0
word infunvals = 0
word retfunc_tag = 0
word break_tag = 0
word cont_tag = 0
@ -308,6 +316,17 @@ word exit
//
//=====================================
//
// Handy functions
//
def strcpy(dst, src)
if ^src
memcpy(dst, src, ^src + 1)
else
^dst = 0
fin
return ^dst
end
//
// Error handler
//
@ -333,14 +352,45 @@ include "toolsrc/parse.pla"
// Look at command line arguments and compile module
//
arg = argNext(argFirst)
if ^arg and ^(arg + 1) == '-'
arg = arg + 2
while TRUE
if toupper(^arg) == 'O'
outflags = outflags | OPTIMIZE
arg++
if ^arg == '2'
outflags = outflags | OPTIMIZE
arg++
fin
elsif toupper(^arg) == 'N'
outflags = outflags | NO_COMBINE
else
break
fin
loop
arg = argNext(arg)
fin
if arg
strcpy(@srcfile, arg)
arg = argNext(arg)
if arg
strcpy(@relfile, arg)
fin
fin
if srcfile and relfile
exit = heapalloc(t_longjmp)
if not setjmp(exit)
//
// Parse source code module
//
parsemodule
puts("Bytes compiled: "); puti(codeptr - codebuff); putln
//
// Write REL file
//
writerel
fin
else
puts("Usage: +PLASM [srcfile]\n")
puts("Usage: +PLASM [-O[2]] <srcfile> <relfile>\n")
fin
done

View File

@ -873,6 +873,7 @@ void interp(code *ip)
*/
default:
fprintf(stderr, "Illegal opcode 0x%02X @ 0x%04X\n", ip[-1], ip - mem_data);
exit(-1);
}
}
}