diff --git a/src/com/webcodepro/applecommander/compiler/ApplesoftCompiler.java b/src/com/webcodepro/applecommander/compiler/ApplesoftCompiler.java index e26f786..f010ad0 100644 --- a/src/com/webcodepro/applecommander/compiler/ApplesoftCompiler.java +++ b/src/com/webcodepro/applecommander/compiler/ApplesoftCompiler.java @@ -143,8 +143,6 @@ public class ApplesoftCompiler implements ApplesoftTokens { public byte[] compile() throws CompileException { StringBuffer programCode = new StringBuffer(); while (hasMoreTokens()) { - sourceLine.setLength(0); - sourceAssembly.setLength(0); ApplesoftToken token = nextToken(); if (!token.isLineNumber()) { throw new CompileException("Expecting a line number."); @@ -163,8 +161,34 @@ public class ApplesoftCompiler implements ApplesoftTokens { programCode.append("\n"); programCode.append(sourceAssembly); programCode.append("\n"); + sourceLine.setLength(0); + sourceAssembly.setLength(0); } programCode.insert(0, buildUsedAddresses()); + for (int i=0; i=0; i--) { + if (buf.charAt(i) == '=') { + buf.deleteCharAt(i); + } + } + String tokenName = buf.toString(); Method method = (Method) commandMethods.get(tokenName); if (method == null) { try { @@ -241,7 +273,8 @@ public class ApplesoftCompiler implements ApplesoftTokens { if (parameter != null) { sourceAssembly.append(" "); sourceAssembly.append(parameter); - if (!usedAddresses.contains(parameter)) { + if (!usedAddresses.contains(parameter) + && knownAddresses.containsKey(parameter)) { usedAddresses.add(parameter); } } @@ -279,17 +312,159 @@ public class ApplesoftCompiler implements ApplesoftTokens { public void evaluateINVERSE() { addAssembly(null, "LDA", "#$3F"); - addAssembly(null, "STA", "$32"); + addAssembly(null, "STA", "INVFLAG"); } public void evaluateNORMAL() { addAssembly(null, "LDA", "#$FF"); - addAssembly(null, "STA", "$32"); + addAssembly(null, "STA", "INVFLAG"); } public void evaluateFLASH() { addAssembly(null, "LDA", "#$7F"); - addAssembly(null, "STA", "$32"); + addAssembly(null, "STA", "INVFLAG"); + } + + protected Variable evaluateExpression() throws CompileException { + // FIXME: no type checking available + // FIXME: needs to evaluate all valid expressions + ApplesoftToken token = nextToken(); + if (token.isString()) { + String value = token.getStringValue(); + Variable variable = null; + for (int i=0; i" + variable.getName()); + addAssembly(null, "LDA", "#<" + variable.getName()); + addAssembly(null, "JSR","MOVFM"); + addAssembly(null, "JSR", "QINT"); + addAssembly(null, "LD" + register, "FACLO"); + } else { + throw new CompileException("Unable to convert to a byte value: " + + variable.getName()); + } + } + + protected void addLoadWordValue(Variable variable, char registerHi, char registerLo) throws CompileException { + if (variable.isConstantInteger()) { + addAssembly(null, "LD" + registerHi, "#>" + variable.getName()); + addAssembly(null, "LD" + registerLo, "#<" + variable.getName()); + } else if (variable.isTypeInteger()) { + addAssembly(null, "LD" + registerHi, variable.getName() + "+1"); + addAssembly(null, "LD" + registerLo, variable.getName()); + } else if (variable.isConstantFloat() || variable.isTypeFloat()) { + addLoadFac(variable); + addAssembly(null, "JSR", "QINT"); + addAssembly(null, "LD" + registerHi, "FACMO"); + addAssembly(null, "LD" + registerLo, "FACLO"); + } else { + throw new CompileException("Unable to convert to a word value: " + + variable.getName()); + } + } + + protected void addLoadAddress(Variable variable, char registerHi, char registerLo) { + addAssembly(null, "LD" + registerHi, "#>" + variable.getName()); + addAssembly(null, "LD" + registerLo, "#<" + variable.getName()); + } + + protected void addLoadFac(Variable variable) throws CompileException { + if (variable.isConstantFloat() || variable.isTypeFloat()) { + addAssembly(null, "LDY", "#>" + variable.getName()); + addAssembly(null, "LDA", "#<" + variable.getName()); + addAssembly(null, "JSR","MOVFM"); + } else { + throw new CompileException("Unable to convert to load FAC for: " + + variable.getName()); + } + } + + public void evaluateHTAB() throws CompileException { + addLoadByteValue(evaluateExpression(), 'A'); + addAssembly(null, "STA", "CH"); + } + + public void evaluateVTAB() throws CompileException { + addLoadByteValue(evaluateExpression(), 'X'); + addAssembly(null, "DEX", null); + addAssembly(null, "STX", "CV"); + addAssembly(null, "JSR", "LF"); + } + + public void evaluateHCOLOR() throws CompileException { + addLoadByteValue(evaluateExpression(), 'X'); + addAssembly(null, "JSR", "SETHCOL"); + } + + public void evaluatePRINT() throws CompileException { + ApplesoftToken token = null; + do { + Variable variable = evaluateExpression(); + if (variable.isConstantFloat() || variable.isTypeFloat()) { + addLoadFac(variable); + addAssembly(null, "JSR", "PRNTFAC"); + } else if (variable.isConstantInteger() || variable.isTypeInteger()) { + addLoadWordValue(variable, 'X', 'A'); + addAssembly(null, "JSR", "LINPRT"); + } else if (variable.isConstantString()) { + addLoadAddress(variable, 'Y', 'A'); + addAssembly(null, "JSR", "STROUT"); + } else if (variable.isTypeString()) { + throw new CompileException("Unable to print string variables yet."); + } + // check if we have separators to skip over... + token = peekToken(); + if (token != null && token.isExpressionSeparator()) { + nextToken(); + } + // see if we should continue processing the print statement + token = peekToken(); + } while (token != null && !token.isEndOfCommand()); + } + + /** + * Indicates if this string is a number. + */ + protected boolean isIntegerNumber(String value) { + for (int i=0; i"); -// sourceAssembly.append(expr); -// sourceAssembly.append("\n"); -// sourceAssembly.append("\tLDA #<"); -// sourceAssembly.append(expr); -// sourceAssembly.append("\n"); -// sourceAssembly.append("\tJSR $EAF9\t; MOVFM\n"); -// sourceAssembly.append("\tJSR $ED2E\t; PRNTFAC\n"); -// } else if (isStringVariable(expr)) { -// sourceAssembly.append("\tLDY #0\n"); -// sourceAssembly.append(":loop\tLDA "); -// sourceAssembly.append(expr); -// sourceAssembly.append(",Y\n"); -// sourceAssembly.append("\tBEQ :end\n"); -// sourceAssembly.append("\tJSR COUT\n"); -// sourceAssembly.append("\tINY\n"); -// sourceAssembly.append("\tBNE :loop\n"); -// sourceAssembly.append(":end\n"); -// } else { -// throw new IllegalArgumentException("Invalid expr in print: " + expr); -// } -// break; // case FOR: // String loopVariable = evaluateExpression(sourceAssembly, sourceLine); // if (!isFloatVariable(loopVariable)) { @@ -385,39 +513,6 @@ public class ApplesoftCompiler implements ApplesoftTokens { // } // } // -// /** -// * Evaluate an expression and return the variable name that -// * contains the value. -// */ -// protected String evaluateExpression(StringBuffer sourceAssembly, StringBuffer sourceLine) { -// // FIXME: no type checking available -// ApplesoftToken token = tokenizer.getNextToken(); -// if (token.isString()) { -// String value = token.getStringValue(); -// sourceLine.append(value); -// if (isIntegerNumber(value)) { -// return addIntegerConstant(value); -// } else if (value.startsWith("\"")) { -// return addStringConstant(value); -// } else { // assume variable name -// return addVariable(value); -// } -// } else { -// throw new IllegalArgumentException("Oops!"); -// } -// } -// -// /** -// * Indicates if this string is a number. -// */ -// protected boolean isIntegerNumber(String value) { -// for (int i=0; i