Skip to content

Commit

Permalink
Spin2 structure implementation update
Browse files Browse the repository at this point in the history
  • Loading branch information
maccasoft committed Apr 17, 2024
1 parent bee9f81 commit ae69e9f
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6491,6 +6491,46 @@ void testStructureRead() throws Exception {
+ "", compile(text));
}

@Test
void testStructureModifiers() throws Exception {
String text = ""
+ "CON\n"
+ " sPoint(x, y)\n"
+ " sLine(sPoint a, sPoint b, BYTE color)\n"
+ "\n"
+ "VAR\n"
+ "\n"
+ " sPoint point\n"
+ " sLine line\n"
+ "\n"
+ "PUB start() | a\n"
+ "\n"
+ " a := @line\n"
+ " a := @line.a\n"
+ " a := @line.b\n"
+ "\n"
+ "";

Assertions.assertEquals(""
+ "' Object header (var size 32)\n"
+ "00000 00000 08 00 00 80 Method start @ $00008 (0 parameters, 0 returns)\n"
+ "00004 00004 13 00 00 00 End\n"
+ "' PUB start() | a\n"
+ "00008 00008 01 (stack size)\n"
+ "' a := @line\n"
+ "00009 00009 C3 7F VAR_ADDRESS VBASE+$00003 (short)\n"
+ "0000B 0000B F0 VAR_WRITE LONG DBASE+$00000 (short)\n"
+ "' a := @line.a\n"
+ "0000C 0000C C3 7F VAR_ADDRESS VBASE+$00003 (short)\n"
+ "0000E 0000E F0 VAR_WRITE LONG DBASE+$00000 (short)\n"
+ "' a := @line.b\n"
+ "0000F 0000F C5 7F VAR_ADDRESS VBASE+$00005 (short)\n"
+ "00011 00011 F0 VAR_WRITE LONG DBASE+$00000 (short)\n"
+ "00012 00012 04 RETURN\n"
+ "00013 00013 00 Padding\n"
+ "", compile(text));
}

String compile(String text) throws Exception {
return compile(text, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ else if (os.size() != 0) {
}

String[] ar = node.getText().split("[\\.]");
if (ar.length == 2 && ("BYTE".equalsIgnoreCase(ar[1]) || "WORD".equalsIgnoreCase(ar[1]) || "LONG".equalsIgnoreCase(ar[1]))) {
if (ar.length >= 2 && ("BYTE".equalsIgnoreCase(ar[ar.length - 1]) || "WORD".equalsIgnoreCase(ar[ar.length - 1]) || "LONG".equalsIgnoreCase(ar[ar.length - 1]))) {
int index = 0;
boolean popIndex = false;
Spin2StatementNode indexNode = null;
Expand All @@ -274,6 +274,17 @@ else if (os.size() != 0) {
if (expression instanceof ObjectContextLiteral) {
expression = context.getLocalSymbol(ar[0].substring(1));
}

if (expression instanceof StructureVariable) {
int i = 1;
while (i < ar.length - 1) {
expression = ((StructureVariable) expression).getVariable(ar[i++]);
if (!(expression instanceof StructureVariable)) {
break;
}
}
}

if (expression != null) {
int n = 0;
if (n < node.getChildCount() && (node.getChild(n) instanceof Spin2StatementNode.Index)) {
Expand All @@ -300,10 +311,10 @@ else if (os.size() != 0) {
}

MemoryOp.Size ss = MemoryOp.Size.Long;
if ("BYTE".equalsIgnoreCase(ar[1])) {
if ("BYTE".equalsIgnoreCase(ar[ar.length - 1])) {
ss = MemoryOp.Size.Byte;
}
else if ("WORD".equalsIgnoreCase(ar[1])) {
else if ("WORD".equalsIgnoreCase(ar[ar.length - 1])) {
ss = MemoryOp.Size.Word;
}
MemoryOp.Base bb = MemoryOp.Base.PBase;
Expand Down Expand Up @@ -381,46 +392,58 @@ else if ("!".equalsIgnoreCase(postEffectNode.getText())) {
expression = context.getLocalSymbol(node.getText().substring(1));
}

if (expression == null) {
String[] segments = node.getText().split("\\.");
if (segments != null && segments.length > 1) {
int i = 0;
expression = context.getLocalSymbol(segments[i++]);
if (expression instanceof SpinObject) {
source.addAll(compileMethodCall(context, method, expression, node, push, false));
return source;
}
if (expression instanceof Method) {
if (isAddress(node.getText())) {
Method methodExpression = (Method) expression;
source.add(new SubAddress(context, methodExpression));
Spin2Method calledMethod = (Spin2Method) methodExpression.getData(Spin2Method.class.getName());
calledMethod.setCalledBy(method);
}
else {
source.addAll(compileMethodCall(context, method, expression, node, push, false));
}
return source;
}

if (expression instanceof StructureVariable) {
int i = 1;
while (i < ar.length) {
expression = ((StructureVariable) expression).getVariable(ar[i++]);
if (!(expression instanceof StructureVariable)) {
throw new CompilerException("syntax error", node.getToken());
break;
}
while (i < segments.length) {
expression = ((StructureVariable) expression).getVariable(segments[i++]);
}
}

if (expression == null && ar.length > 0) {
expression = context.getLocalSymbol(ar[0]);
if (expression == null && isAbsoluteAddress(ar[0])) {
expression = context.getLocalSymbol(ar[0].substring(2));
}
if (expression == null && isAddress(ar[0])) {
expression = context.getLocalSymbol(ar[0].substring(1));
}
if (expression instanceof ObjectContextLiteral) {
expression = context.getLocalSymbol(ar[0].substring(1));
}

if (expression instanceof StructureVariable) {
int i = 1;
while (i < ar.length) {
expression = ((StructureVariable) expression).getVariable(ar[i++]);
if (!(expression instanceof StructureVariable)) {
break;
}
}
if ((expression instanceof StructureVariable)) {
throw new CompilerException("syntax error", node.getToken());
}
if (i < segments.length) {
throw new CompilerException("syntax error", node.getToken());
}
}
}

if (expression != null) {
if (expression instanceof SpinObject) {
source.addAll(compileMethodCall(context, method, expression, node, push, false));
return source;
}
else if (expression instanceof Method) {
if (isAddress(node.getText())) {
Method methodExpression = (Method) expression;
source.add(new SubAddress(context, methodExpression));
Spin2Method calledMethod = (Spin2Method) methodExpression.getData(Spin2Method.class.getName());
calledMethod.setCalledBy(method);
}
else {
source.addAll(compileMethodCall(context, method, expression, node, push, false));
}
}
else if (expression instanceof Variable) {
if (expression instanceof Variable) {
if (isAddress(node.getText())) {
int index = 0;
boolean popIndex = false;
Expand Down Expand Up @@ -1593,9 +1616,20 @@ protected List<Spin2Bytecode> leftAssign(Context context, Spin2Method method, Sp
throw new CompilerException("syntax error", node.getToken());
}

String[] s = node.getText().split("[\\.]");
if (s.length == 2 && ("BYTE".equalsIgnoreCase(s[1]) || "WORD".equalsIgnoreCase(s[1]) || "LONG".equalsIgnoreCase(s[1]))) {
Expression expression = context.getLocalSymbol(s[0]);
String[] ar = node.getText().split("[\\.]");
if (ar.length >= 2 && ("BYTE".equalsIgnoreCase(ar[ar.length - 1]) || "WORD".equalsIgnoreCase(ar[ar.length - 1]) || "LONG".equalsIgnoreCase(ar[ar.length - 1]))) {
Expression expression = context.getLocalSymbol(ar[0]);

if (expression instanceof StructureVariable) {
int i = 1;
while (i < ar.length - 1) {
expression = ((StructureVariable) expression).getVariable(ar[i++]);
if (!(expression instanceof StructureVariable)) {
break;
}
}
}

if (expression == null) {
throw new CompilerException("undefined symbol " + node.getText(), node.getToken());
}
Expand Down Expand Up @@ -1643,10 +1677,10 @@ protected List<Spin2Bytecode> leftAssign(Context context, Spin2Method method, Sp
}

MemoryOp.Size ss = MemoryOp.Size.Long;
if ("BYTE".equalsIgnoreCase(s[1])) {
if ("BYTE".equalsIgnoreCase(ar[1])) {
ss = MemoryOp.Size.Byte;
}
else if ("WORD".equalsIgnoreCase(s[1])) {
else if ("WORD".equalsIgnoreCase(ar[1])) {
ss = MemoryOp.Size.Word;
}
MemoryOp.Base bb = MemoryOp.Base.PBase;
Expand Down Expand Up @@ -1871,30 +1905,20 @@ else if ("FIELD".equalsIgnoreCase(node.getText()) && node.getChildCount() != 0)
}
}
else {
Expression expression = null;
Expression expression = context.getLocalSymbol(node.getText());

String[] segments = node.getText().split("\\.");
if (segments != null && segments.length > 1) {
int i = 0;
expression = context.getLocalSymbol(segments[i++]);
if (!(expression instanceof StructureVariable)) {
throw new CompilerException("syntax error", node.getToken());
}
while (i < segments.length) {
expression = ((StructureVariable) expression).getVariable(segments[i++]);
if (!(expression instanceof StructureVariable)) {
break;
if (expression == null && ar.length > 0) {
expression = context.getLocalSymbol(ar[0]);

if (expression instanceof StructureVariable) {
int i = 1;
while (i < ar.length) {
expression = ((StructureVariable) expression).getVariable(ar[i++]);
if (!(expression instanceof StructureVariable)) {
break;
}
}
}
if ((expression instanceof StructureVariable)) {
throw new CompilerException("syntax error", node.getToken());
}
if (i < segments.length) {
throw new CompilerException("syntax error", node.getToken());
}
}
else {
expression = context.getLocalSymbol(node.getText());
}

if (expression == null) {
Expand Down Expand Up @@ -2373,11 +2397,25 @@ List<Spin2Bytecode> compileVariableRead(Context context, Spin2Method method, Exp
}
}

int index = 0;
boolean hasIndex = false;
boolean popIndex = false;
boolean field = node.getText().startsWith("^@");

int n = 0;
if (n < node.getChildCount() && (node.getChild(n) instanceof Spin2StatementNode.Index)) {
indexNode = node.getChild(n++);
popIndex = true;
try {
Expression exp = buildConstantExpression(context, indexNode);
if (exp.isConstant()) {
index = exp.getNumber().intValue();
hasIndex = true;
popIndex = false;
}
} catch (Exception e) {
// Do nothing
}
}
if (n < node.getChildCount() && ".".equals(node.getChild(n).getText())) {
n++;
Expand All @@ -2389,31 +2427,27 @@ List<Spin2Bytecode> compileVariableRead(Context context, Spin2Method method, Exp
}
bitfieldNode = node.getChild(n++);
}
if (expression instanceof StructureVariable) {
if (n < node.getChildCount() && node.getChild(n).getText().startsWith(".")) {
String[] ar = node.getChild(n).getText().split("[\\.]");

int i = 1;
while (i < ar.length) {
expression = ((StructureVariable) expression).getVariable(ar[i++]);
if (!(expression instanceof StructureVariable)) {
break;
}
}
n++;
}
}
if (n < node.getChildCount() && isPostEffect(node.getChild(n))) {
postEffectNode = node.getChild(n++);
}
if (n < node.getChildCount()) {
throw new CompilerException("unexpected " + node.getChild(n).getText(), node.getChild(n));
}

int index = 0;
boolean hasIndex = false;
boolean popIndex = false;

if (indexNode != null) {
popIndex = true;
try {
Expression exp = buildConstantExpression(context, indexNode);
if (exp.isConstant()) {
index = exp.getNumber().intValue();
hasIndex = true;
popIndex = false;
}
} catch (Exception e) {
// Do nothing
}
}

if (bitfieldNode != null) {
int bitfield = compileBitfield(context, method, bitfieldNode, source);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,7 @@ else if (token.type == Token.STRING) {
tokens.add(new TokenMarker(token.start, token.start + dot, leftId));
}

dot = token.getText().lastIndexOf('.');
switch (token.getText().substring(dot + 1).toUpperCase()) {
case "LONG":
case "WORD":
Expand Down

0 comments on commit ae69e9f

Please sign in to comment.