Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/bc.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ typedef struct BcLexKeyword

/// A macro for the number of keywords bc has. This has to be updated if any are
/// added. This is for the redefined_kws field of the BcVm struct.
#define BC_LEX_NKWS (37)
#define BC_LEX_NKWS (38)

#else // BC_ENABLE_EXTRA_MATH

/// A macro for the number of keywords bc has. This has to be updated if any are
/// added. This is for the redefined_kws field of the BcVm struct.
#define BC_LEX_NKWS (33)
#define BC_LEX_NKWS (34)

#endif // BC_ENABLE_EXTRA_MATH

Expand Down
6 changes: 6 additions & 0 deletions include/lang.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ typedef enum BcInst

#endif // DC_ENABLED

/// Pop the global stacks.
BC_INST_GLOBAL_POP,

/// Invalid instruction.
BC_INST_INVALID,

Expand Down Expand Up @@ -409,6 +412,9 @@ typedef struct BcFunc
#if BC_ENABLED
/// True if the function is a void function.
bool voidfn;

/// True if the function is a stack function (uses global stacks).
bool stackfn;
#endif // BC_ENABLED

} BcFunc;
Expand Down
3 changes: 3 additions & 0 deletions include/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ typedef enum BcLexType
/// bc else keyword.
BC_LEX_KW_ELSE,

/// bc GLOBAL_POP keyword.
BC_LEX_KW_GLOBAL_POP,

#if DC_ENABLED

/// dc extended registers keyword.
Expand Down
3 changes: 3 additions & 0 deletions include/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ typedef struct BcParse
/// True if the bc parser just entered a function and an auto statement
/// would be valid.
bool auto_part;

/// True if the bc parser is in a stack function.
bool stackfn;
#endif // BC_ENABLED

} BcParse;
Expand Down
4 changes: 3 additions & 1 deletion include/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ extern const char bc_program_esc_seqs[];
&&lbl_BC_INST_QUIT, \
&&lbl_BC_INST_NQUIT, \
&&lbl_BC_INST_EXEC_STACK_LEN, \
&&lbl_BC_INST_GLOBAL_POP, \
&&lbl_BC_INST_INVALID, \
}

Expand Down Expand Up @@ -822,6 +823,7 @@ extern const char bc_program_esc_seqs[];
&&lbl_BC_INST_MODEXP, \
&&lbl_BC_INST_DIVMOD, \
&&lbl_BC_INST_PRINT_STREAM, \
&&lbl_BC_INST_GLOBAL_POP, \
&&lbl_BC_INST_INVALID, \
}

Expand Down Expand Up @@ -949,7 +951,7 @@ extern const char bc_program_esc_seqs[];
&&lbl_BC_INST_LOAD, &&lbl_BC_INST_PUSH_VAR, \
&&lbl_BC_INST_PUSH_TO_VAR, &&lbl_BC_INST_QUIT, \
&&lbl_BC_INST_NQUIT, &&lbl_BC_INST_EXEC_STACK_LEN, \
&&lbl_BC_INST_INVALID, \
&&lbl_BC_INST_GLOBAL_POP, &&lbl_BC_INST_INVALID, \
}

#else // BC_ENABLE_EXTRA_MATH
Expand Down
3 changes: 3 additions & 0 deletions include/status.h
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,9 @@ typedef enum BcErr
/// Non-POSIX void error.
BC_ERR_POSIX_VOID,

/// Non-POSIX stack error.
BC_ERR_POSIX_STACK,

/// Non-POSIX brace position used error.
BC_ERR_POSIX_BRACE,

Expand Down
56 changes: 37 additions & 19 deletions src/bc_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1369,36 +1369,40 @@ bc_parse_loopExit(BcParse* p, BcLexType type)
static void
bc_parse_func(BcParse* p)
{
bool comma = false, voidfn;
bool comma = false, voidfn, stackfn;
uint16_t flags;
size_t idx;

bc_lex_next(&p->l);

// Must have a name.
if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
voidfn = stackfn = false;

while (p->l.t == BC_LEX_NAME)
{
if (!strcmp(p->l.str.v, "void"))
{
if (BC_IS_POSIX) bc_parse_err(p, BC_ERR_POSIX_VOID);
if (BC_ERR(voidfn)) bc_parse_err(p, BC_ERR_PARSE_FUNC); // Duplicate void
voidfn = true;
bc_lex_next(&p->l);
}
else if (!strcmp(p->l.str.v, "stack"))
{
if (BC_IS_POSIX) bc_parse_err(p, BC_ERR_POSIX_STACK);
if (BC_ERR(stackfn)) bc_parse_err(p, BC_ERR_PARSE_FUNC); // Duplicate stack
stackfn = true;
bc_lex_next(&p->l);
}
else break; // Not a function type keyword, must be function name
}

// If the name is "void", and POSIX is not on, mark as void.
voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&
!strcmp(p->l.str.v, "void"));
// Must have a function name.
if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_FUNC);

// We can safely do this because the expected token should not overwrite the
// function name.
bc_lex_next(&p->l);

// If we *don't* have another name, then void is the name of the function.
voidfn = (voidfn && p->l.t == BC_LEX_NAME);

// With a void function, allow POSIX to complain and get a new token.
if (voidfn)
{
bc_parse_err(p, BC_ERR_POSIX_VOID);

// We can safely do this because the expected token should not overwrite
// the function name.
bc_lex_next(&p->l);
}

// Must have a left paren.
if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_FUNC);

Expand All @@ -1414,6 +1418,7 @@ bc_parse_func(BcParse* p)
// Update the function pointer and stuff in the parser and set its void.
bc_parse_updateFunc(p, idx);
p->func->voidfn = voidfn;
p->func->stackfn = stackfn;

bc_lex_next(&p->l);

Expand Down Expand Up @@ -1821,6 +1826,17 @@ bc_parse_stmt(BcParse* p)
break;
}

case BC_LEX_KW_GLOBAL_POP:
{
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
bc_parse_push(p, BC_INST_GLOBAL_POP);
break;
}

case BC_LEX_KW_QUIT:
{
// Quit is a compile-time command. We don't exit directly, so the vm
Expand Down Expand Up @@ -2393,6 +2409,8 @@ bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next)
break;
}



case BC_LEX_KW_SCALE:
{
// This is a leaf and cannot come right after a leaf.
Expand Down
1 change: 1 addition & 0 deletions src/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,7 @@ const BcLexKeyword bc_lex_kws[] = {
BC_LEX_KW_ENTRY("leading_zero", 12, false),
BC_LEX_KW_ENTRY("stream", 6, false),
BC_LEX_KW_ENTRY("else", 4, false),
BC_LEX_KW_ENTRY("global_pop", 11, false),
};

/// The length of the list of bc keywords.
Expand Down
1 change: 1 addition & 0 deletions src/lang.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ bc_func_init(BcFunc* f, const char* name)

f->nparams = 0;
f->voidfn = false;
f->stackfn = BC_G;
}

#endif // BC_ENABLED
Expand Down
35 changes: 30 additions & 5 deletions src/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ bc_program_read(BcProgram* p)

#if BC_ENABLED
// Push on the globals stack if necessary.
if (BC_G) bc_program_prepGlobals(p);
if (f->stackfn) bc_program_prepGlobals(p);
#endif // BC_ENABLED

// Set up a new BcInstPtr.
Expand Down Expand Up @@ -1814,7 +1814,7 @@ bc_program_call(BcProgram* p, const char* restrict code, size_t* restrict bgn)
assert(BC_PROG_STACK(&p->results, nargs));

// Prepare the globals' stacks.
if (BC_G) bc_program_prepGlobals(p);
if (f->stackfn) bc_program_prepGlobals(p);

// Push the arguments onto the stacks of their respective parameters.
for (i = 0; i < nargs; ++i)
Expand Down Expand Up @@ -1949,7 +1949,7 @@ bc_program_return(BcProgram* p, uchar inst)
bc_program_retire(p, nresults);

// Pop the globals, if necessary.
if (BC_G) bc_program_popGlobals(p, false);
if (f->stackfn) bc_program_popGlobals(p, false);

// Pop the stack. This is what causes the function to actually "return."
bc_vec_pop(&p->stack);
Expand Down Expand Up @@ -2731,7 +2731,15 @@ bc_program_globalSetting(BcProgram* p, uchar inst)
#if BC_ENABLED
else if (inst == BC_INST_GLOBAL_STACKS)
{
val = (BC_G != 0);
if (p->stack.len > 0)
{
BcInstPtr* ip = bc_vec_top(&p->stack);
val = ((BcFunc*) bc_vec_item(&p->fns, ip->func))->stackfn || (BC_G != 0);
}
else
{
val = (BC_G != 0);
}
}
#endif // BC_ENABLED
#if DC_ENABLED
Expand Down Expand Up @@ -3028,7 +3036,7 @@ bc_program_reset(BcProgram* p)

#if BC_ENABLED
// Clear the globals' stacks.
if (BC_G) bc_program_popGlobals(p, true);
if (f->stackfn) bc_program_popGlobals(p, true);
#endif // BC_ENABLED

// Clear the bytecode vector of the main function.
Expand Down Expand Up @@ -3507,6 +3515,23 @@ bc_program_exec(BcProgram* p)
BC_PROG_JUMP(inst, code, ip);
}

BC_PROG_LBL(BC_INST_GLOBAL_POP):
// clang-format on
{
if (p->stack.len > 0)
{
BcInstPtr* ip = bc_vec_top(&p->stack);
BcFunc* f = bc_vec_item(&p->fns, ip->func);

if (f->stackfn)
{
bc_program_popGlobals(p, false);
bc_program_prepGlobals(p);
}
}
BC_PROG_JUMP(inst, code, ip);
}

// clang-format off
BC_PROG_LBL(BC_INST_POP):
// clang-format on
Expand Down