Merge remote-tracking branch 'upstream/master'
diff --git a/bc/include/bc/bc.h b/bc/include/bc/bc.h
index 8916729..4a2df7f 100644
--- a/bc/include/bc/bc.h
+++ b/bc/include/bc/bc.h
@@ -46,7 +46,9 @@
BC_STATUS_VM_FILE_NOT_EXECUTABLE,
BC_STATUS_VM_SIGACTION_FAIL,
BC_STATUS_VM_INVALID_STMT,
+ BC_STATUS_VM_INVALID_EXPR,
BC_STATUS_VM_INVALID_STRING,
+ BC_STATUS_VM_INVALID_NAME,
BC_STATUS_VM_PRINT_ERR,
BC_STATUS_VM_BREAK,
BC_STATUS_VM_CONTINUE,
diff --git a/bc/include/bc/data.h b/bc/include/bc/data.h
index f9ac7fe..2e4465f 100644
--- a/bc/include/bc/data.h
+++ b/bc/include/bc/data.h
@@ -31,13 +31,13 @@
BC_EXPR_PLUS,
BC_EXPR_MINUS,
- BC_EXPR_ASSIGN,
- BC_EXPR_ASSIGN_PLUS,
- BC_EXPR_ASSIGN_MINUS,
+ BC_EXPR_ASSIGN_POWER,
BC_EXPR_ASSIGN_MULTIPLY,
BC_EXPR_ASSIGN_DIVIDE,
BC_EXPR_ASSIGN_MODULUS,
- BC_EXPR_ASSIGN_POWER,
+ BC_EXPR_ASSIGN_PLUS,
+ BC_EXPR_ASSIGN_MINUS,
+ BC_EXPR_ASSIGN,
BC_EXPR_REL_EQUAL,
BC_EXPR_REL_LESS_EQ,
@@ -111,7 +111,7 @@
BcExprType type;
union {
char* string;
- BcStack* expr_stack;
+ BcStack* exprs;
BcCall* call;
BcArrayElem* elem;
};
@@ -146,7 +146,7 @@
char* string;
struct BcStmtList* list;
- BcStack* expr_stack;
+ BcStack* exprs;
BcIf* if_stmt;
BcWhile* while_stmt;
BcFor* for_stmt;
@@ -193,6 +193,19 @@
} BcLocal;
+typedef struct BcTemp {
+
+ bool is_num;
+
+ union {
+
+ fxdpnt* num;
+ const char* name;
+
+ };
+
+} BcTemp;
+
typedef struct BcFunc {
char* name;
@@ -263,4 +276,8 @@
BcStatus bc_local_initArray(BcLocal* local, const char* name, uint32_t nelems);
void bc_local_free(void* local);
+BcStatus bc_temp_initNum(BcTemp* temp, const char* val);
+BcStatus bc_temp_initName(BcTemp* temp, const char* name);
+void bc_temp_free(void* temp);
+
#endif // BC_DATA_H
diff --git a/bc/include/bc/lex.h b/bc/include/bc/lex.h
index b612a80..6b37ee7 100644
--- a/bc/include/bc/lex.h
+++ b/bc/include/bc/lex.h
@@ -24,13 +24,13 @@
TOKEN(BC_LEX_OP_PLUS) \
TOKEN(BC_LEX_OP_MINUS) \
\
- TOKEN(BC_LEX_OP_ASSIGN) \
- TOKEN(BC_LEX_OP_ASSIGN_PLUS) \
- TOKEN(BC_LEX_OP_ASSIGN_MINUS) \
+ TOKEN(BC_LEX_OP_ASSIGN_POWER) \
TOKEN(BC_LEX_OP_ASSIGN_MULTIPLY) \
TOKEN(BC_LEX_OP_ASSIGN_DIVIDE) \
TOKEN(BC_LEX_OP_ASSIGN_MODULUS) \
- TOKEN(BC_LEX_OP_ASSIGN_POWER) \
+ TOKEN(BC_LEX_OP_ASSIGN_PLUS) \
+ TOKEN(BC_LEX_OP_ASSIGN_MINUS) \
+ TOKEN(BC_LEX_OP_ASSIGN) \
\
TOKEN(BC_LEX_OP_REL_EQUAL) \
TOKEN(BC_LEX_OP_REL_LESS_EQ) \
diff --git a/bc/include/bc/program.h b/bc/include/bc/program.h
index 2c0c3db..a495c3b 100644
--- a/bc/include/bc/program.h
+++ b/bc/include/bc/program.h
@@ -13,6 +13,10 @@
uint32_t stmt_idx;
+ uint32_t scale;
+ uint32_t ibase;
+ uint32_t obase;
+
BcStack ctx_stack;
BcStack locals;
diff --git a/bc/main.c b/bc/main.c
index becb133..1f16945 100644
--- a/bc/main.c
+++ b/bc/main.c
@@ -1,5 +1,8 @@
+#include <locale.h>
+
#include <bc/bc.h>
int main(int argc, char* argv[]) {
+ setlocale(LC_ALL, "");
return bc_main(argc, argv);
}
diff --git a/bc/src/bc.c b/bc/src/bc.c
index e70ccfe..6fdade5 100644
--- a/bc/src/bc.c
+++ b/bc/src/bc.c
@@ -51,6 +51,8 @@
"runtime",
"runtime",
"runtime",
+ "runtime",
+ "runtime",
};
@@ -90,7 +92,9 @@
"file is not executable",
"could not install signal handler",
"invalid statement; this is most likely a bug in bc",
+ "invalid expression; this is most likely a bug in bc",
"invalid string",
+ "invalid name/identifier",
"print error",
"break statement outside loop; "
"this is a bug in bc (parser should have caught it)",
diff --git a/bc/src/data.c b/bc/src/data.c
index c3bfa98..0a326b0 100644
--- a/bc/src/data.c
+++ b/bc/src/data.c
@@ -440,9 +440,9 @@
if (bc_stmt_sizes[type]) {
- stmt->data.expr_stack = malloc(bc_stmt_sizes[type]);
+ stmt->data.exprs = malloc(bc_stmt_sizes[type]);
- if (!stmt->data.expr_stack) {
+ if (!stmt->data.exprs) {
return BC_STATUS_MALLOC_FAIL;
}
}
@@ -465,8 +465,8 @@
case BC_STMT_EXPR:
case BC_STMT_RETURN:
{
- bc_stack_free(stmt->data.expr_stack);
- free(stmt->data.expr_stack);
+ bc_stack_free(stmt->data.exprs);
+ free(stmt->data.exprs);
break;
}
@@ -527,7 +527,7 @@
}
}
- stmt->data.expr_stack = NULL;
+ stmt->data.exprs = NULL;
}
BcIf* bc_if_create() {
@@ -615,8 +615,8 @@
case BC_EXPR_LENGTH:
case BC_EXPR_SQRT:
{
- bc_stack_free(e->expr_stack);
- free(e->expr_stack);
+ bc_stack_free(e->exprs);
+ free(e->exprs);
break;
}
@@ -706,3 +706,41 @@
l->num_elems = 0;
}
}
+
+BcStatus bc_temp_initNum(BcTemp* temp, const char* val) {
+
+ temp->is_num = true;
+
+ if (val) {
+ temp->num = arb_str2fxdpnt(val);
+ }
+ else {
+ temp->num = arb_alloc(BC_PROGRAM_DEF_SIZE);
+ }
+
+ return BC_STATUS_SUCCESS;
+}
+
+BcStatus bc_temp_initName(BcTemp* temp, const char* name) {
+
+ temp->is_num = false;
+
+ if (!name) {
+ return BC_STATUS_VM_INVALID_NAME;
+ }
+
+ temp->name = name;
+
+ return BC_STATUS_SUCCESS;
+}
+
+void bc_temp_free(void* temp) {
+
+ BcTemp* t;
+
+ t = (BcTemp*) temp;
+
+ if (t->is_num) {
+ arb_free(t->num);
+ }
+}
diff --git a/bc/src/lex.c b/bc/src/lex.c
index 30b2882..b71e100 100644
--- a/bc/src/lex.c
+++ b/bc/src/lex.c
@@ -553,31 +553,16 @@
size_t len = i - lex->idx;
- size_t backslashes = 0;
- for (size_t j = lex->idx; j < i; ++j) {
- c = lex->buffer[j];
- backslashes += c == '\\' && lex->buffer[j + 1] == '\n' ? 1 : 0;
- }
-
- token->string = malloc(len - backslashes + 1);
+ token->string = malloc(len + 1);
if (token->string == NULL) {
return BC_STATUS_MALLOC_FAIL;
}
const char* start = lex->buffer + lex->idx;
- size_t hits = 0;
for (size_t j = 0; j < len; ++j) {
-
- char c = start[j];
-
- if (hits < backslashes && c == '\\' && start[j + 1] == '\n') {
- ++hits;
- continue;
- }
-
- token->string[j - hits] = c;
+ token->string[j] = start[j];
}
token->string[len] = '\0';
@@ -645,8 +630,8 @@
size_t i = 0;
char c = buffer[i];
- while (c && (isdigit(c) || (c >= 'A' && c <= 'F') || (c == '.' && !point) ||
- (c == '\\' && buffer[i + 1] == '\n')))
+ while (c && ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
+ (c == '.' && !point) || (c == '\\' && buffer[i + 1] == '\n')))
{
if (c == '\\') {
++i;
@@ -715,7 +700,7 @@
size_t i = 0;
char c = buffer[i];
- while (islower(c) || isdigit(c) || c == '_') {
+ while ((c >= 'a' && c<= 'z') || (c >= '0' && c <= '9') || c == '_') {
++i;
c = buffer[i];
}
diff --git a/bc/src/parse.c b/bc/src/parse.c
index 4472dcf..1c24293 100644
--- a/bc/src/parse.c
+++ b/bc/src/parse.c
@@ -715,7 +715,7 @@
break;
}
- status = bc_parse_expr(parse, stmt.data.expr_stack);
+ status = bc_parse_expr(parse, stmt.data.exprs);
if (status) {
bc_stmt_free(&stmt);
@@ -999,13 +999,13 @@
break;
}
- case BC_LEX_OP_ASSIGN:
- case BC_LEX_OP_ASSIGN_PLUS:
- case BC_LEX_OP_ASSIGN_MINUS:
+ case BC_LEX_OP_ASSIGN_POWER:
case BC_LEX_OP_ASSIGN_MULTIPLY:
case BC_LEX_OP_ASSIGN_DIVIDE:
case BC_LEX_OP_ASSIGN_MODULUS:
- case BC_LEX_OP_ASSIGN_POWER:
+ case BC_LEX_OP_ASSIGN_PLUS:
+ case BC_LEX_OP_ASSIGN_MINUS:
+ case BC_LEX_OP_ASSIGN:
{
if (prev != BC_EXPR_VAR && prev != BC_EXPR_ARRAY_ELEM &&
prev != BC_EXPR_SCALE && prev != BC_EXPR_IBASE &&
@@ -1215,8 +1215,8 @@
expr.type = ((BcExpr*) bc_stack_top(exprs))->type;
- if (expr.type < BC_EXPR_ASSIGN ||
- expr.type > BC_EXPR_ASSIGN_POWER ||
+ if (expr.type < BC_EXPR_ASSIGN_POWER ||
+ expr.type > BC_EXPR_ASSIGN ||
paren_first)
{
expr.type = BC_EXPR_PRINT;
@@ -1367,7 +1367,7 @@
char* name;
name = parse->token.string;
- expr.expr_stack = NULL;
+ expr.exprs = NULL;
status = bc_lex_next(&parse->lex, &parse->token);
@@ -1381,9 +1381,9 @@
*type = BC_EXPR_ARRAY_ELEM;
expr.string = name;
- expr.expr_stack = malloc(sizeof(BcStack));
+ expr.exprs = malloc(sizeof(BcStack));
- if (!expr.expr_stack) {
+ if (!expr.exprs) {
return BC_STATUS_MALLOC_FAIL;
}
@@ -1393,7 +1393,7 @@
goto name_err;
}
- status = bc_parse_expr(parse, expr.expr_stack);
+ status = bc_parse_expr(parse, expr.exprs);
if (status) {
goto name_err;
@@ -1430,7 +1430,7 @@
status = bc_stack_push(exprs, &expr);
- if (status && expr.expr_stack) {
+ if (status && expr.exprs) {
goto name_err;
}
@@ -1438,8 +1438,8 @@
name_err:
- free(expr.expr_stack);
- expr.expr_stack = NULL;
+ free(expr.exprs);
+ expr.exprs = NULL;
return status;
}
@@ -1584,13 +1584,13 @@
return status;
}
- expr.expr_stack = malloc(sizeof(BcStack));
+ expr.exprs = malloc(sizeof(BcStack));
- if (!expr.expr_stack) {
+ if (!expr.exprs) {
return BC_STATUS_MALLOC_FAIL;
}
- status = bc_parse_expr(parse, expr.expr_stack);
+ status = bc_parse_expr(parse, expr.exprs);
if (status) {
goto init_err;
@@ -1611,7 +1611,7 @@
init_err:
- free(expr.expr_stack);
+ free(expr.exprs);
return status;
}
@@ -1638,13 +1638,13 @@
expr.type = BC_EXPR_SCALE_FUNC;
*type = BC_EXPR_SCALE_FUNC;
- expr.expr_stack = malloc(sizeof(BcStack));
+ expr.exprs = malloc(sizeof(BcStack));
- if (!expr.expr_stack) {
+ if (!expr.exprs) {
return BC_STATUS_MALLOC_FAIL;
}
- status = bc_parse_expr(parse, expr.expr_stack);
+ status = bc_parse_expr(parse, expr.exprs);
if (status) {
goto parse_err;
@@ -1671,7 +1671,7 @@
parse_err:
- free(expr.expr_stack);
+ free(expr.exprs);
return status;
}
@@ -1813,16 +1813,16 @@
stmt.type = BC_STMT_RETURN;
- stmt.data.expr_stack = malloc(sizeof(BcStack));
+ stmt.data.exprs = malloc(sizeof(BcStack));
- if (!stmt.data.expr_stack) {
+ if (!stmt.data.exprs) {
return BC_STATUS_MALLOC_FAIL;
}
if (parse->token.type == BC_LEX_NEWLINE ||
parse->token.type == BC_LEX_SEMICOLON)
{
- status = bc_stack_init(stmt.data.expr_stack, sizeof(BcExpr), bc_expr_free);
+ status = bc_stack_init(stmt.data.exprs, sizeof(BcExpr), bc_expr_free);
if (status) {
goto parse_err;
@@ -1831,7 +1831,7 @@
expr.type = BC_EXPR_NUMBER;
expr.string = NULL;
- status = bc_stack_push(stmt.data.expr_stack, &expr);
+ status = bc_stack_push(stmt.data.exprs, &expr);
if (status) {
goto push_err;
@@ -1839,7 +1839,7 @@
}
else {
- status = bc_parse_expr(parse, stmt.data.expr_stack);
+ status = bc_parse_expr(parse, stmt.data.exprs);
if (status) {
goto parse_err;
@@ -1856,11 +1856,11 @@
push_err:
- bc_stack_free(stmt.data.expr_stack);
+ bc_stack_free(stmt.data.exprs);
parse_err:
- free(stmt.data.expr_stack);
+ free(stmt.data.exprs);
return status;
}
@@ -1913,14 +1913,14 @@
return status;
}
- status = bc_parse_expr(parse, stmt.data.expr_stack);
+ status = bc_parse_expr(parse, stmt.data.exprs);
if (status) {
goto expr_err;
}
expr.type = BC_EXPR_PRINT;
- status = bc_stack_push(stmt.data.expr_stack, &expr);
+ status = bc_stack_push(stmt.data.exprs, &expr);
if (status) {
goto parse_err;
@@ -1961,11 +1961,11 @@
parse_err:
- bc_stack_free(stmt.data.expr_stack);
+ bc_stack_free(stmt.data.exprs);
expr_err:
- free(stmt.data.expr_stack);
+ free(stmt.data.exprs);
return status;
}
diff --git a/bc/src/program.c b/bc/src/program.c
index 2cb20ad..c56e8f1 100644
--- a/bc/src/program.c
+++ b/bc/src/program.c
@@ -9,7 +9,7 @@
static BcStatus bc_program_execList(BcProgram* p, BcStmtList* list);
static BcStatus bc_program_printString(const char* str);
-static BcStatus bc_program_execExpr(BcProgram* p, BcStmt* stmt,
+static BcStatus bc_program_execExpr(BcProgram* p, BcStack* exprs,
fxdpnt* num, bool print);
BcStatus bc_program_init(BcProgram* p, const char* file) {
@@ -59,7 +59,7 @@
goto local_err;
}
- st = bc_stack_init(&p->temps, sizeof(fxdpnt), (BcFreeFunc) arb_free);
+ st = bc_stack_init(&p->temps, sizeof(BcTemp), bc_temp_free);
if (st) {
goto temps_err;
@@ -123,7 +123,38 @@
}
BcStatus bc_program_exec(BcProgram* p) {
- return bc_program_execList(p, p->list);
+
+ BcStmtList* list;
+ BcStatus status;
+
+ status = bc_program_execList(p, p->list);
+
+ if (status) {
+ return status;
+ }
+
+ while (p->list->idx >= BC_PROGRAM_MAX_STMTS) {
+
+ if (p->list->next) {
+
+ list = p->list;
+ p->list = list->next;
+
+ bc_list_destruct(list);
+ }
+ else {
+
+ bc_list_destruct(p->list);
+
+ p->list = bc_list_create();
+
+ if (!p->list) {
+ return BC_STATUS_MALLOC_FAIL;
+ }
+ }
+ }
+
+ return BC_STATUS_SUCCESS;
}
void bc_program_free(BcProgram* p) {
@@ -174,7 +205,7 @@
case BC_STMT_EXPR:
{
- status = bc_program_execExpr(p, stmt, &result, true);
+ status = bc_program_execExpr(p, stmt->data.exprs, &result, true);
if (status) {
break;
@@ -355,8 +386,231 @@
return BC_STATUS_SUCCESS;
}
-static BcStatus bc_program_execExpr(BcProgram* p, BcStmt* stmt,
+static BcStatus bc_program_execExpr(BcProgram* p, BcStack* exprs,
fxdpnt* num, bool print)
{
+ BcStatus status;
+ uint32_t idx;
+ BcExpr* expr;
+ BcTemp temp;
+ uint32_t temp_len;
+ fxdpnt temp_num;
+ status = BC_STATUS_SUCCESS;
+
+ temp_len = p->temps.len;
+
+ idx = exprs->len - 1;
+
+ while (idx < exprs->len) {
+
+ expr = bc_stack_item(exprs, idx);
+
+ if (!expr) {
+ return BC_STATUS_VM_INVALID_EXPR;
+ }
+
+ switch (expr->type) {
+
+ case BC_EXPR_INC_PRE:
+ case BC_EXPR_DEC_PRE:
+ {
+ break;
+ }
+
+ case BC_EXPR_INC_POST:
+ case BC_EXPR_DEC_POST:
+ {
+ break;
+ }
+
+ case BC_EXPR_NEGATE:
+ {
+ break;
+ }
+
+ case BC_EXPR_POWER:
+ {
+ break;
+ }
+
+ case BC_EXPR_MULTIPLY:
+ {
+ break;
+ }
+
+ case BC_EXPR_DIVIDE:
+ {
+ break;
+ }
+
+ case BC_EXPR_MODULUS:
+ {
+ break;
+ }
+
+ case BC_EXPR_PLUS:
+ {
+ break;
+ }
+
+ case BC_EXPR_MINUS:
+ {
+ break;
+ }
+
+ case BC_EXPR_ASSIGN_POWER:
+ case BC_EXPR_ASSIGN_MULTIPLY:
+ case BC_EXPR_ASSIGN_DIVIDE:
+ case BC_EXPR_ASSIGN_MODULUS:
+ case BC_EXPR_ASSIGN_PLUS:
+ case BC_EXPR_ASSIGN_MINUS:
+ {
+ // Fallthrough.
+ }
+ case BC_EXPR_ASSIGN:
+ {
+ break;
+ }
+
+ case BC_EXPR_REL_EQUAL:
+ case BC_EXPR_REL_LESS_EQ:
+ case BC_EXPR_REL_GREATER_EQ:
+ case BC_EXPR_REL_NOT_EQ:
+ case BC_EXPR_REL_LESS:
+ case BC_EXPR_REL_GREATER:
+ {
+ break;
+ }
+
+ case BC_EXPR_BOOL_NOT:
+ {
+ break;
+ }
+
+ case BC_EXPR_BOOL_OR:
+ {
+ break;
+ }
+
+ case BC_EXPR_BOOL_AND:
+ {
+ break;
+ }
+
+ case BC_EXPR_NUMBER:
+ {
+ status = bc_temp_initNum(&temp, expr->string);
+
+ if (status) {
+ break;
+ }
+
+ status = bc_stack_push(&p->temps, &temp);
+
+ break;
+ }
+
+ case BC_EXPR_VAR:
+ {
+ break;
+ }
+
+ case BC_EXPR_ARRAY_ELEM:
+ {
+ break;
+ }
+
+ case BC_EXPR_FUNC_CALL:
+ {
+ break;
+ }
+
+ case BC_EXPR_SCALE:
+ {
+ break;
+ }
+
+ case BC_EXPR_SCALE_FUNC:
+ {
+ break;
+ }
+
+ case BC_EXPR_IBASE:
+ {
+ break;
+ }
+
+ case BC_EXPR_OBASE:
+ {
+ break;
+ }
+
+ case BC_EXPR_LAST:
+ {
+ break;
+ }
+
+ case BC_EXPR_LENGTH:
+ {
+ break;
+ }
+
+ case BC_EXPR_READ:
+ {
+ break;
+ }
+
+ case BC_EXPR_SQRT:
+ {
+ status = bc_program_execExpr(p, expr->exprs, &temp_num, false);
+
+ if (status) {
+ break;
+ }
+
+ if (temp_num.sign != '-') {
+
+ status = bc_temp_initNum(&temp, NULL);
+
+ if (status) {
+ break;
+ }
+
+ arb_newton_sqrt(&temp_num, temp.num, 10, p->scale);
+ }
+ else {
+ status = BC_STATUS_VM_NEG_SQRT;
+ }
+
+ break;
+ }
+
+ case BC_EXPR_PRINT:
+ {
+ // TODO: Store to last and print.
+ if (!print) {
+ break;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ status = BC_STATUS_VM_INVALID_EXPR;
+ break;
+ }
+ }
+ }
+
+ if (status) {
+ return status;
+ }
+
+ if (p->temps.len != temp_len) {
+ return BC_STATUS_VM_INVALID_EXPR;
+ }
+
+ return status;
}