diff --git a/c02.c b/c02.c index fb2ff16..e051cf1 100644 --- a/c02.c +++ b/c02.c @@ -45,6 +45,8 @@ void init() invasc = FALSE; mskasc = FALSE; fcase = FALSE; + xsnvar[0] = 0; + ysnvar[0] = 0; } /* Reads and parses the next Word in Source File */ diff --git a/doc/c02.txt b/doc/c02.txt index b19845b..c0c2d30 100644 --- a/doc/c02.txt +++ b/doc/c02.txt @@ -1,4 +1,4 @@ -INTRODUCTION +INTRODUCTION C02 is a simple C-syntax language designed to generate highly optimized code for the 6502 microprocessor. The C02 specification is a highly @@ -60,7 +60,12 @@ DIRECTIVES Directives are special instructions to the compiler. They do not directy generate compiled code. A directive is denoted by a leading # character. -C02 currently supports only one directive. + +DEFINE + +The #define directive creates a named constant. + +INCLUDE The #include directive causes the compiler to read and process and external file. In most cases, #include directives will be used with libraries of @@ -110,7 +115,7 @@ A decimal number consists of one to three decimal digits (0 through 9). A hexadecimal number consists of a $ followed by two hexadecimal digits (0 through 9 or A through F). -A character literals consists of a single character surrounded by ' symbols. +A character literal consists of a single character surrounded by ' symbols. A ' character may be specified by escaping it with a \. Examples: @@ -478,6 +483,24 @@ Examples: Note: An implicit assignment generates an STA opcode with the variable as the operand. +PLURAL ASSIGNMENTS + +C02 allows a function to return up to three values by specifying multiple +variables, separated by commas, to the left of the assignment operator (=). + +The first and second variables to be assigned may be either simple variables +or subscripted array elements. The third variable, if used, may only be a +simple variable. Registers are not allowed in plural assignments. + +Examples: + row, col = scnpos(); //Get current screen position + cr, mn, mx = cpmnmx(a, b); //Compare two values, return min and max + lwr[i], upr[i] = tolwup(txt[i]); //Convert char to lower and upper case + +Note: When compiled, a plural assignment generates an STX for the third +assignment (if specified), an STY for the second assignment and an STA for +the first assignment. + GOTO STATEMENT A goto statement unconditionally transfers program execution to the @@ -512,9 +535,9 @@ Examples: Note: In order to optimize the compiled code, the if and else statements are to 6502 relative branch instructions. This limits the amount of generated code between the if statement and the end of the if/else block -to slightly less than 127 characters. This should be sufficient in most -cases, but larger code blocks can be accommodated using function calls or -goto statements. +to slightly less than 127 bytes. This should be sufficient in most cases, +but larger code blocks can be accommodated using function calls or goto +statements. SELECT, CASE, AND DEFAULT STATEMENTS diff --git a/parse.c b/parse.c index 930c3a9..1c7b9a3 100644 --- a/parse.c +++ b/parse.c @@ -71,7 +71,7 @@ char getnxt() void skpspc() { //DEBUG("Skipping Spaces\n", 0); - if (isspc()) CCMNT(' '); + if (isspc()) CCMNT(' '); //Add only the first space to comments while (isspc()) getnxt(); } @@ -387,14 +387,6 @@ void prsopr() skpspc(); } -/* Process Array Index */ -void prcidx(char *name, char *index) -{ - if (strlen(index)) { - asmlin("LDX", index); - strcat(name,",X"); - } -} /* Generate Post-Operation Error */ void poperr(char* name) @@ -407,7 +399,10 @@ void poperr(char* name) void prcpst(char* name, char *index) { DEBUG("Processing post operation '%c'\n", oper); - prcidx(name, index); + if (strlen(index)) { + asmlin("LDX", index); + strcat(name,",X"); + } switch(oper) { case '+': diff --git a/parse.h b/parse.h index 938ef7c..a2bc11b 100644 --- a/parse.h +++ b/parse.h @@ -4,7 +4,7 @@ #define TF(x) (x) ? TRUE : FALSE; -enum stypes {CONSTANT, VARIABLE, ARRAY, FUNCTION}; //Symbol Types +enum stypes {CONSTANT, VARIABLE, REGISTER, ARRAY, FUNCTION}; //Symbol Types enum etypes {ETDEF, ETMAC}; //Definition Types char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup) diff --git a/stmnt.c b/stmnt.c index 31df55c..805c5f8 100644 --- a/stmnt.c +++ b/stmnt.c @@ -59,61 +59,115 @@ void prssif(char trmntr) { setlbl(tmplbl); //Emit End of Expression Label } +/* Process Array Index */ +void prcidx(int idxtyp, char *name, char *index) +{ + if (strlen(index)) { + if (idxtyp == CONSTANT) { + strcat(name, "+"); + strcat(name, index); + } + else { + asmlin("LDX", index); + strcat(name,",X"); + } + } +} /* Process Assignment */ void prcasn(char trmntr) { expect('='); - DEBUG("Processing assignment of variable '%s'\n", asnvar); if (look('(')) prssif(trmntr); //Parse Shortcut If else prsxpr(trmntr); //Parse Expression + DEBUG("Processing X assignment variable '%s'\n", xsnvar); + if (xsnvar[0]) { + asmlin("STX", xsnvar); + xsnvar[0] = 0; + } + DEBUG("Processing Y assignment variable '%s'\n", ysnvar); + if (ysnvar[0]) { + if (strlen(ysnidx)) + prcidx(ysnivt, ysnvar, ysnidx); + asmlin("STY", ysnvar); + ysnvar[0] = 0; + } + DEBUG("Processing assignment variable '%s'\n", asnvar); if (strcmp(asnvar, "X")==0) asmlin("TAX", ""); else if (strcmp(asnvar, "Y")==0) asmlin("TAY", ""); else if ((strcmp(asnvar, "A")!=0)) { - if (strlen(asnidx)) { - if (asnivt == CONSTANT) { - strcat(asnvar, "+"); - strcat(asnvar, asnidx); - } - else { - asmlin("LDX", asnidx); - strcat(asnvar,",X"); - } - } + if (strlen(asnidx)) + prcidx(asnivt, asnvar, asnidx); asmlin("STA", asnvar); } } -/* Process Variable at Beginning of Statement */ +/* Parse and Return Array Index and Type */ +int getidx(char* idx) +{ + prsidx(); //Parse Array Index + if (valtyp == CONSTANT) + strncpy(idx, word, VARLEN); + else + strncpy(idx, value, VARLEN); + DEBUG("Set assigned index to %s\n", asnidx); + return valtyp; +} + +/* Process Assignment Variable(s) */ void prcvar(char trmntr) { chksym(TRUE, word); - strcpy(asnvar, word); //sav variable to assign to - if (valtyp == VARIABLE && look(';')) { + strcpy(asnvar, word); //save variable to assign to + asntyp = valtyp; //Set Assigned Varable Type + DEBUG("Set STA variable to %s\n", asnvar); + if (asntyp == VARIABLE && look(';')) { asmlin("STA", asnvar); return; } - if (valtyp == ARRAY) { - prsidx(); //Parse Array Index - asnivt = valtyp; - if (asnivt == CONSTANT) - strncpy(asnidx, word, VARLEN); - else - strncpy(asnidx, value, VARLEN); + if (asntyp == ARRAY) { + asnivt = getidx(asnidx); //Get Array Index and Type + DEBUG("Set STA index to %s\n", asnidx); + DEBUG("Set STA index type to %d\n", asnivt); } else asnidx[0] = 0; if (ispopr()) { if (prspst(trmntr, asnvar, asnidx)) //Parse Post Operator expctd("post operator"); + /*refactor - put a return here and remove followig else*/ } - else + else { + if (look(',')) { + if (asntyp == REGISTER) { + ERROR("Register %s not allowed in plural assignment\n", asnvar, EXIT_FAILURE); + } + prsvar(FALSE); //get variable name + strcpy(ysnvar, word); + DEBUG("Set STY variable to %s\n", ysnvar); + if (valtyp == ARRAY) { + ysnivt = getidx(ysnidx); //Get Array Index and Type + DEBUG("Set STY index to %s\n", ysnidx); + DEBUG("Set STY index type to %d\n", ysnivt); + } + else + ysnidx[0] = 0; + if (look(',')) { + prsvar(FALSE); //get variable name + strcpy(xsnvar, word); + DEBUG("Set STX variable to %s\n", xsnvar); + if (valtyp == ARRAY) { + ERROR("Array element not allowed in third assignment\n", 0, EXIT_FAILURE); + } + } + } prcasn(trmntr); + } } /* Parse 'asm' String Parameter */ @@ -141,7 +195,7 @@ void pasm() asmlin(opcode, word); } -/* Parse and Compile and Assignment */ +/* Parse and Compile an Assignment */ void prsasn(char trmntr) { getwrd(); //Get Variable to be Assigned diff --git a/stmnt.h b/stmnt.h index c11d10f..dc7ed1e 100644 --- a/stmnt.h +++ b/stmnt.h @@ -3,8 +3,13 @@ ************************************/ char asnvar[VARLEN+1]; //Assigned Variable Name +int asntyp; //Assigned Variable Type char asnidx[VARLEN+1] ; //Assigned Variable Index int asnivt; //Assigned Index Variable Type +char ysnvar[VARLEN+1]; //Assigned Y Variable Name +char ysnidx[VARLEN+1] ; //Assigned Variable Index +int ysnivt; //Assigned Index Variable Type +char xsnvar[VARLEN+1]; //Assigned X Variable Name char xstmnt[LINELEN]; //Expected Statement diff --git a/vars.c b/vars.c index 492ebbf..6efeacb 100644 --- a/vars.c +++ b/vars.c @@ -36,8 +36,11 @@ int fndvar(char *name) void chksym(int alwreg, char *name) { if (strlen(name) == 1 && strchr("AXY", name[0])) { - if (alwreg) return; - else ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE); + if (alwreg && valtyp != ARRAY) { + valtyp = REGISTER; + return; + } + ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE); } if (!fndvar(name)) ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE);