mirror of
https://github.com/bradgrantham/apple2a.git
synced 2024-06-06 14:29:28 +00:00
Add IF/THEN statement.
This commit is contained in:
parent
86b0e366bd
commit
5a755ca3c5
|
@ -7,7 +7,12 @@ extern void pushax();
|
||||||
extern void popax();
|
extern void popax();
|
||||||
extern void tosaddax();
|
extern void tosaddax();
|
||||||
|
|
||||||
extern char ptr1;
|
// Two bytes each.
|
||||||
|
extern unsigned int ptr1;
|
||||||
#pragma zpsym ("ptr1");
|
#pragma zpsym ("ptr1");
|
||||||
|
|
||||||
|
// One byte each.
|
||||||
|
extern unsigned char tmp1;
|
||||||
|
#pragma zpsym ("tmp1");
|
||||||
|
|
||||||
#endif // __EXPORTER_H__
|
#endif // __EXPORTER_H__
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
.import popax
|
.import popax
|
||||||
.import tosaddax
|
.import tosaddax
|
||||||
.importzp ptr1
|
.importzp ptr1
|
||||||
|
.importzp tmp1
|
||||||
.export _pushax := pushax
|
.export _pushax := pushax
|
||||||
.export _popax := popax
|
.export _popax := popax
|
||||||
.export _tosaddax := tosaddax
|
.export _tosaddax := tosaddax
|
||||||
.exportzp _ptr1 = ptr1
|
.exportzp _ptr1 = ptr1
|
||||||
|
.exportzp _tmp1 = tmp1
|
||||||
|
|
||||||
|
|
56
main.c
56
main.c
|
@ -8,6 +8,7 @@ uint8_t *title = "Apple IIa";
|
||||||
uint8_t title_length = 9;
|
uint8_t title_length = 9;
|
||||||
|
|
||||||
// 6502 instructions.
|
// 6502 instructions.
|
||||||
|
#define I_ORA_ZPG 0x05
|
||||||
#define I_CLC 0x18
|
#define I_CLC 0x18
|
||||||
#define I_JSR 0x20
|
#define I_JSR 0x20
|
||||||
#define I_SEC 0x38
|
#define I_SEC 0x38
|
||||||
|
@ -21,6 +22,8 @@ uint8_t title_length = 9;
|
||||||
#define I_LDA_ZPG 0xA5
|
#define I_LDA_ZPG 0xA5
|
||||||
#define I_LDX_ZPG 0xA6
|
#define I_LDX_ZPG 0xA6
|
||||||
#define I_LDA_IMM 0xA9
|
#define I_LDA_IMM 0xA9
|
||||||
|
#define I_BNE_REL 0xD0
|
||||||
|
#define I_BEQ_REL 0xF0
|
||||||
|
|
||||||
// Tokens.
|
// Tokens.
|
||||||
#define T_HOME 0x80
|
#define T_HOME 0x80
|
||||||
|
@ -40,6 +43,8 @@ uint8_t title_length = 9;
|
||||||
#define T_EQUALS 0x8E
|
#define T_EQUALS 0x8E
|
||||||
#define T_LESS_THAN 0x8F
|
#define T_LESS_THAN 0x8F
|
||||||
#define T_GOTO 0x90
|
#define T_GOTO 0x90
|
||||||
|
#define T_IF 0x91
|
||||||
|
#define T_THEN 0x92
|
||||||
|
|
||||||
// Line number used for "no line number".
|
// Line number used for "no line number".
|
||||||
#define INVALID_LINE_NUMBER 0xFFFF
|
#define INVALID_LINE_NUMBER 0xFFFF
|
||||||
|
@ -76,6 +81,8 @@ static uint8_t *TOKEN[] = {
|
||||||
"=",
|
"=",
|
||||||
"<",
|
"<",
|
||||||
"GOTO",
|
"GOTO",
|
||||||
|
"IF",
|
||||||
|
"THEN",
|
||||||
};
|
};
|
||||||
static int16_t TOKEN_COUNT = sizeof(TOKEN)/sizeof(TOKEN[0]);
|
static int16_t TOKEN_COUNT = sizeof(TOKEN)/sizeof(TOKEN[0]);
|
||||||
|
|
||||||
|
@ -454,9 +461,13 @@ static void set_up_compile(void) {
|
||||||
static void compile_buffer(uint8_t *buffer, uint16_t line_number) {
|
static void compile_buffer(uint8_t *buffer, uint16_t line_number) {
|
||||||
uint8_t *s = buffer;
|
uint8_t *s = buffer;
|
||||||
uint8_t done;
|
uint8_t done;
|
||||||
|
// Keep track of addresses that point to the end of the line.
|
||||||
|
uint8_t **end_of_line_address[4];
|
||||||
|
uint8_t end_of_line_count = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int8_t error = 0;
|
int8_t error = 0;
|
||||||
|
int8_t continue_statement = 0;
|
||||||
|
|
||||||
// Default to being done after one statement.
|
// Default to being done after one statement.
|
||||||
done = 1;
|
done = 1;
|
||||||
|
@ -538,13 +549,47 @@ static void compile_buffer(uint8_t *buffer, uint16_t line_number) {
|
||||||
g_compiled[g_compiled_length++] = addr >> 8;
|
g_compiled[g_compiled_length++] = addr >> 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (*s == T_IF) {
|
||||||
|
uint16_t saved_compiled_length = g_compiled_length;
|
||||||
|
s += 1;
|
||||||
|
// Parse conditional expression.
|
||||||
|
s = compile_expression(s);
|
||||||
|
// Check if AX is zero. Or the two bytes together, through the zero page.
|
||||||
|
g_compiled[g_compiled_length++] = I_STX_ZPG;
|
||||||
|
g_compiled[g_compiled_length++] = (uint8_t) &tmp1;
|
||||||
|
g_compiled[g_compiled_length++] = I_ORA_ZPG;
|
||||||
|
g_compiled[g_compiled_length++] = (uint8_t) &tmp1;
|
||||||
|
// If so, skip to end of this line.
|
||||||
|
g_compiled[g_compiled_length++] = I_BNE_REL;
|
||||||
|
g_compiled[g_compiled_length++] = 3; // Skip over absolute jump.
|
||||||
|
g_compiled[g_compiled_length++] = I_JMP_ABS;
|
||||||
|
// TODO Check for overflow of end_of_line_address:
|
||||||
|
end_of_line_address[end_of_line_count++] = (uint8_t **) &g_compiled[g_compiled_length];
|
||||||
|
g_compiled[g_compiled_length++] = 0; // Address of next line.
|
||||||
|
g_compiled[g_compiled_length++] = 0; // Address of next line.
|
||||||
|
|
||||||
|
if (*s == T_THEN) {
|
||||||
|
// Skip THEN and continue
|
||||||
|
s += 1;
|
||||||
|
continue_statement = 1;
|
||||||
|
} else if (*s == T_GOTO) {
|
||||||
|
// Just continue, we'll pick it up after the loop.
|
||||||
|
continue_statement = 1;
|
||||||
|
} else {
|
||||||
|
// Must be THEN or GOTO. Erase what we've done.
|
||||||
|
g_compiled_length = saved_compiled_length;
|
||||||
|
error = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we're at the end of our statement.
|
// Now we're at the end of our statement.
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if (*s == ':') {
|
if (continue_statement) {
|
||||||
|
// No problem, just continue from here.
|
||||||
|
done = 0;
|
||||||
|
} else if (*s == ':') {
|
||||||
// Skip colon.
|
// Skip colon.
|
||||||
s += 1;
|
s += 1;
|
||||||
|
|
||||||
|
@ -557,14 +602,23 @@ static void compile_buffer(uint8_t *buffer, uint16_t line_number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
end_of_line_count = 0;
|
||||||
if (line_number != INVALID_LINE_NUMBER) {
|
if (line_number != INVALID_LINE_NUMBER) {
|
||||||
compile_load_ax(line_number);
|
compile_load_ax(line_number);
|
||||||
add_call(syntax_error_in_line);
|
add_call(syntax_error_in_line);
|
||||||
} else {
|
} else {
|
||||||
add_call(syntax_error);
|
add_call(syntax_error);
|
||||||
}
|
}
|
||||||
|
// TODO This won't work after a GOSUB. Maybe we should have our
|
||||||
|
// own stack for that.
|
||||||
|
add_return();
|
||||||
}
|
}
|
||||||
} while (!done);
|
} while (!done);
|
||||||
|
|
||||||
|
// Fill in the places where we needed the address of the end of the line.
|
||||||
|
while (end_of_line_count > 0) {
|
||||||
|
*end_of_line_address[--end_of_line_count] = &g_compiled[g_compiled_length];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue
Block a user