changed array implementation (size is no longer part of type)
This commit is contained in:
parent
68093f96e9
commit
c503ff31c5
|
@ -102,6 +102,14 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the parse tree, then records the returned type in the type
|
||||||
|
* annotations and returns it too.
|
||||||
|
*
|
||||||
|
* @param tree
|
||||||
|
* the tree to visit
|
||||||
|
* @return the evaluated type of the tree
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Type visit(ParseTree tree) {
|
public Type visit(ParseTree tree) {
|
||||||
Type type = super.visit(tree);
|
Type type = super.visit(tree);
|
||||||
|
@ -150,16 +158,13 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
||||||
Variable<Type> var = an.symbols.put(ctx.IDENTIFIER().getText(), visit(ctx.type()));
|
Variable<Type> var = an.symbols.put(ctx.IDENTIFIER().getText(), visit(ctx.type()));
|
||||||
var.setConstant(ctx.CONSTANT() != null);
|
var.setConstant(ctx.CONSTANT() != null);
|
||||||
an.variables.put(ctx, var);
|
an.variables.put(ctx, var);
|
||||||
an.variableRoot.put(var, ctx.getParent());
|
an.variableRoot.put(var, ctx.getParent().getParent());
|
||||||
|
|
||||||
if (var.getType() instanceof TupleType)
|
if (var.getType() instanceof TupleType)
|
||||||
log.severe(getError(ctx, Messages.getString("BoppiChecker.4"), //$NON-NLS-1$
|
log.severe(getError(ctx, Messages.getString("BoppiChecker.4"), //$NON-NLS-1$
|
||||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.BOOLTYPE),
|
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.BOOLTYPE),
|
||||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.CHARTYPE),
|
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.CHARTYPE),
|
||||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.INTTYPE)));
|
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.INTTYPE)));
|
||||||
|
|
||||||
if (var.getType() instanceof ReferenceType)
|
|
||||||
var.assign();
|
|
||||||
} catch (SymbolTableException e) {
|
} catch (SymbolTableException e) {
|
||||||
log.severe(getError(ctx, e.getMessage()));
|
log.severe(getError(ctx, e.getMessage()));
|
||||||
}
|
}
|
||||||
|
@ -200,6 +205,13 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
||||||
return SimpleType.VOID;
|
return SimpleType.VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type visitDefineArray(DefineArrayContext ctx) {
|
||||||
|
checkConstraint(visit(ctx.size), SimpleType.INT, ctx);
|
||||||
|
|
||||||
|
return new ArrayType(visit(ctx.type()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type visitGetVariable(GetVariableContext ctx) {
|
public Type visitGetVariable(GetVariableContext ctx) {
|
||||||
return visit(ctx.variable());
|
return visit(ctx.variable());
|
||||||
|
@ -301,6 +313,16 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
||||||
return SimpleType.VOID;
|
return SimpleType.VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type visitLiteralArray(LiteralArrayContext ctx) {
|
||||||
|
Type elementType = visit(ctx.expr(0));
|
||||||
|
|
||||||
|
for (int i = 1; i < ctx.expr().size(); i++)
|
||||||
|
checkConstraint(visit(ctx.expr(i)), elementType, ctx);
|
||||||
|
|
||||||
|
return new ArrayType(elementType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type visitLiteralBoolean(LiteralBooleanContext ctx) {
|
public Type visitLiteralBoolean(LiteralBooleanContext ctx) {
|
||||||
return SimpleType.BOOL;
|
return SimpleType.BOOL;
|
||||||
|
@ -390,15 +412,7 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type visitTypeArray(TypeArrayContext ctx) {
|
public Type visitTypeArray(TypeArrayContext ctx) {
|
||||||
int size = 0;
|
return new ArrayType(visit(ctx.type()));
|
||||||
|
|
||||||
try {
|
|
||||||
size = Integer.parseInt(ctx.LITERAL10().getText());
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
log.severe(getError(ctx, Messages.getString("BoppiChecker.6"), ctx.LITERAL10().getText())); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ArrayType(size, visit(ctx.type()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -35,6 +35,22 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
OFFSET_RETURN_VAL = new Num(-12), OFFSET_AL = new Num(-16), OFFSET_FUNCREF_ADDR = ZERO,
|
OFFSET_RETURN_VAL = new Num(-12), OFFSET_AL = new Num(-16), OFFSET_FUNCREF_ADDR = ZERO,
|
||||||
OFFSET_FUNCREF_ARP = new Num(4), OFFSET_FUNCREF_ARSIZE = new Num(8), OFFSET_REF_COUNT = new Num(-8),
|
OFFSET_FUNCREF_ARP = new Num(4), OFFSET_FUNCREF_ARSIZE = new Num(8), OFFSET_REF_COUNT = new Num(-8),
|
||||||
OFFSET_REF_SIZE = new Num(-4);
|
OFFSET_REF_SIZE = new Num(-4);
|
||||||
|
/**
|
||||||
|
* Unknown type used in a read expression
|
||||||
|
*/
|
||||||
|
public static final Num ERROR_INPUT_UNKNOWN_TYPE = new Num(0x72656164);
|
||||||
|
/**
|
||||||
|
* Unknown type used in a print expression
|
||||||
|
*/
|
||||||
|
public static final Num ERROR_OUTPUT_UNKNOWN_TYPE = new Num(0x77726974);
|
||||||
|
/**
|
||||||
|
* Array out of bounds
|
||||||
|
*/
|
||||||
|
public static final Num ERROR_OUT_OF_BOUNDS = new Num(0x616f6f62);
|
||||||
|
/**
|
||||||
|
* Negative array size
|
||||||
|
*/
|
||||||
|
public static final Num ERROR_ILLEGAL_ARRAY_SIZE = new Num(0x616e737a);
|
||||||
|
|
||||||
private Program prog;
|
private Program prog;
|
||||||
private Annotations an;
|
private Annotations an;
|
||||||
|
@ -531,29 +547,6 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Reg visitDeclare(DeclareContext ctx) {
|
|
||||||
Variable<Type> var = an.variables.get(ctx);
|
|
||||||
Type t = var.getType();
|
|
||||||
|
|
||||||
if (t instanceof ReferenceType) {
|
|
||||||
|
|
||||||
regPool.withReg((addr) -> {
|
|
||||||
emit("load var address", OpCode.addI, arp, new Num(var.getOffset()), addr); //$NON-NLS-1$
|
|
||||||
|
|
||||||
if (t instanceof ArrayType) {
|
|
||||||
ArrayType type = (ArrayType) t;
|
|
||||||
regPool.withReg((temp) -> {
|
|
||||||
malloc(temp, type.getReferenceSize());
|
|
||||||
emit("link array", OpCode.store, temp, addr); //$NON-NLS-1$
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare named function:
|
* Declare named function:
|
||||||
* <ol>
|
* <ol>
|
||||||
|
@ -570,7 +563,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Reg visitDeclareFunction(DeclareFunctionContext ctx) {
|
public Reg visitDeclareFunction(DeclareFunctionContext ctx) {
|
||||||
ReferenceType type = (ReferenceType) an.variables.get(ctx).getType();
|
FunctionType funcType = (FunctionType) an.variables.get(ctx).getType();
|
||||||
String base = "define " + ctx.IDENTIFIER().getText() + " - "; //$NON-NLS-1$ //$NON-NLS-2$
|
String base = "define " + ctx.IDENTIFIER().getText() + " - "; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
Label skip = makeLabel("s"); //$NON-NLS-1$
|
Label skip = makeLabel("s"); //$NON-NLS-1$
|
||||||
|
@ -579,7 +572,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
|
|
||||||
Reg result = visit(ctx.body);
|
Reg result = visit(ctx.body);
|
||||||
|
|
||||||
if (((FunctionType) an.variables.get(ctx).getType()).getReturn() != SimpleType.VOID)
|
if (funcType.getReturn() != SimpleType.VOID)
|
||||||
emit(base + "move result", OpCode.storeAI, result, arp, OFFSET_RETURN_VAL); //$NON-NLS-1$
|
emit(base + "move result", OpCode.storeAI, result, arp, OFFSET_RETURN_VAL); //$NON-NLS-1$
|
||||||
|
|
||||||
if (PROPER_CLEANUP_INSTEAD_OF_PROPER_CLOSURES)
|
if (PROPER_CLEANUP_INSTEAD_OF_PROPER_CLOSURES)
|
||||||
|
@ -607,7 +600,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
emit(base + "skip target", skip, OpCode.nop); //$NON-NLS-1$
|
emit(base + "skip target", skip, OpCode.nop); //$NON-NLS-1$
|
||||||
|
|
||||||
regPool.withReg((r1, r2) -> {
|
regPool.withReg((r1, r2) -> {
|
||||||
malloc(r2, type.getReferenceSize());
|
malloc(r2, funcType.getReferenceSize());
|
||||||
emit(base + "load target address", OpCode.loadI, new Num(callAddress), r1); //$NON-NLS-1$
|
emit(base + "load target address", OpCode.loadI, new Num(callAddress), r1); //$NON-NLS-1$
|
||||||
emit(base + "set target address", OpCode.storeAI, r1, r2, OFFSET_FUNCREF_ADDR); //$NON-NLS-1$
|
emit(base + "set target address", OpCode.storeAI, r1, r2, OFFSET_FUNCREF_ADDR); //$NON-NLS-1$
|
||||||
emit(base + "copy ARP", OpCode.storeAI, arp, r2, OFFSET_FUNCREF_ARP); //$NON-NLS-1$
|
emit(base + "copy ARP", OpCode.storeAI, arp, r2, OFFSET_FUNCREF_ARP); //$NON-NLS-1$
|
||||||
|
@ -622,6 +615,32 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reg visitDefineArray(DefineArrayContext ctx) {
|
||||||
|
Type elementType = ((ArrayType) an.types.get(ctx)).getType();
|
||||||
|
Reg arrSize = visit(ctx.size);
|
||||||
|
|
||||||
|
emit("produce array size", OpCode.multI, arrSize, new Num(elementType.getSize()), arrSize); //$NON-NLS-1$
|
||||||
|
|
||||||
|
return regPool.blockReg(arrSize, () -> regPool.withReg((temp) -> {
|
||||||
|
Label validSize = makeLabel("aszt"), invalidSize = makeLabel("aszf");
|
||||||
|
emit("check size non negative", OpCode.cmp_GE, arrSize, RegisterPool.ZERO, temp);
|
||||||
|
emit("", OpCode.cbr, temp, validSize, invalidSize);
|
||||||
|
emit("invalid array size", invalidSize, OpCode.haltI, ERROR_ILLEGAL_ARRAY_SIZE);
|
||||||
|
emit("valid array size", validSize, OpCode.nop);
|
||||||
|
|
||||||
|
malloc(temp, arrSize);
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the value on the address pointed to by the variable context.
|
||||||
|
* Because the array length is not stored by itself, it will be calculated
|
||||||
|
* here from the size property.
|
||||||
|
*
|
||||||
|
* @see BoppiBaseVisitor#visitGetVariable(GetVariableContext)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Reg visitGetVariable(GetVariableContext ctx) {
|
public Reg visitGetVariable(GetVariableContext ctx) {
|
||||||
Type type = an.types.get(ctx);
|
Type type = an.types.get(ctx);
|
||||||
|
@ -635,6 +654,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
incrementReference(type, result);
|
incrementReference(type, result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (ctx.variable() instanceof VariablePropertyContext) {
|
||||||
|
VariablePropertyContext vpctx = (VariablePropertyContext) ctx.variable();
|
||||||
|
Type varType = an.types.get(vpctx.variable());
|
||||||
|
|
||||||
|
if (varType instanceof ArrayType)
|
||||||
|
emit("divide by element size", OpCode.divI, result, //$NON-NLS-1$
|
||||||
|
new Num(((ArrayType) varType).getType().getSize()), result);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,9 +745,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
|
|
||||||
return regPool.withReg((i, temp1) -> {
|
return regPool.withReg((i, temp1) -> {
|
||||||
regPool.withReg((temp2) -> {
|
regPool.withReg((temp2) -> {
|
||||||
Label cond = makeLabel("aeqc"), loop = makeLabel("aeql"), end = makeLabel("aeqe"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
Label equalSize = makeLabel("aeqs"), cond = makeLabel("aeqc"), loop = makeLabel("aeql"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
end = makeLabel("aeqe"); //$NON-NLS-1$
|
||||||
|
|
||||||
emit("iterate from 0", OpCode.loadI, ZERO, i); //$NON-NLS-1$
|
emit("load size lhs", OpCode.loadAI, lhs, OFFSET_REF_SIZE, temp1); //$NON-NLS-1$
|
||||||
|
emit("load size rhs", OpCode.loadAI, rhs, OFFSET_REF_SIZE, temp2); //$NON-NLS-1$
|
||||||
|
emit("compare array sizes", OpCode.cmp_EQ, temp1, temp2, temp1); //$NON-NLS-1$
|
||||||
|
emit("loop if equal", OpCode.cbr, temp1, equalSize, end); //$NON-NLS-1$
|
||||||
|
|
||||||
|
emit("iterate from 0", equalSize, OpCode.loadI, ZERO, i); //$NON-NLS-1$
|
||||||
emit("equality true", OpCode.loadI, new Num(1), temp1); //$NON-NLS-1$
|
emit("equality true", OpCode.loadI, new Num(1), temp1); //$NON-NLS-1$
|
||||||
|
|
||||||
emit("load arr size", cond, OpCode.loadAI, lhs, OFFSET_REF_SIZE, temp2); //$NON-NLS-1$
|
emit("load arr size", cond, OpCode.loadAI, lhs, OFFSET_REF_SIZE, temp2); //$NON-NLS-1$
|
||||||
|
@ -767,6 +801,26 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
return visit(ctx.expr());
|
return visit(ctx.expr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reg visitLiteralArray(LiteralArrayContext ctx) {
|
||||||
|
int elements = ctx.expr().size();
|
||||||
|
int elementSize = ((ArrayType) an.types.get(ctx)).getType().getSize();
|
||||||
|
|
||||||
|
return regPool.withReg((addr) -> {
|
||||||
|
malloc(addr, elements * elementSize);
|
||||||
|
|
||||||
|
for (int i = 0; i < elements; i++) {
|
||||||
|
Reg result = visit(ctx.expr(i));
|
||||||
|
Num offset = new Num(i * elementSize);
|
||||||
|
|
||||||
|
if (elementSize == 1)
|
||||||
|
emit("store array element", OpCode.cstoreAI, result, addr, offset); //$NON-NLS-1$
|
||||||
|
else
|
||||||
|
emit("store array element", OpCode.storeAI, result, addr, offset); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reg visitLiteralBoolean(LiteralBooleanContext ctx) {
|
public Reg visitLiteralBoolean(LiteralBooleanContext ctx) {
|
||||||
return regPool.withReg((reg) -> {
|
return regPool.withReg((reg) -> {
|
||||||
|
@ -852,7 +906,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
emit("save to var " + expr.getText(), OpCode.cstore, temp, addr); //$NON-NLS-1$
|
emit("save to var " + expr.getText(), OpCode.cstore, temp, addr); //$NON-NLS-1$
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
|
emit("reading unknown type", OpCode.haltI, ERROR_INPUT_UNKNOWN_TYPE); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -897,7 +951,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
emit("check array index", OpCode.cmp_GE, offset, RegisterPool.ZERO, r2); //$NON-NLS-1$
|
emit("check array index", OpCode.cmp_GE, offset, RegisterPool.ZERO, r2); //$NON-NLS-1$
|
||||||
emit("check array index", OpCode.and, r1, r2, r2); //$NON-NLS-1$
|
emit("check array index", OpCode.and, r1, r2, r2); //$NON-NLS-1$
|
||||||
emit("check array index", OpCode.cbr, r2, inBounds, outOfBounds); //$NON-NLS-1$
|
emit("check array index", OpCode.cbr, r2, inBounds, outOfBounds); //$NON-NLS-1$
|
||||||
emit("array index out of bounds", outOfBounds, OpCode.haltI, new Num(0x616f6f62)); //$NON-NLS-1$
|
emit("array index out of bounds", outOfBounds, OpCode.haltI, ERROR_OUT_OF_BOUNDS); //$NON-NLS-1$
|
||||||
|
|
||||||
emit("multiply index by size", inBounds, OpCode.multI, offset, new Num(type.getType().getSize()), //$NON-NLS-1$
|
emit("multiply index by size", inBounds, OpCode.multI, offset, new Num(type.getType().getSize()), //$NON-NLS-1$
|
||||||
offset);
|
offset);
|
||||||
|
@ -914,8 +968,10 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
Type innerType = an.types.get(ctx.variable());
|
Type innerType = an.types.get(ctx.variable());
|
||||||
Reg addr = visit(ctx.variable());
|
Reg addr = visit(ctx.variable());
|
||||||
|
|
||||||
|
emit("get object address", OpCode.load, addr, addr); //$NON-NLS-1$
|
||||||
|
|
||||||
if (innerType instanceof ArrayType) {
|
if (innerType instanceof ArrayType) {
|
||||||
emit("get size", OpCode.loadAI, addr, OFFSET_REF_SIZE, addr); //$NON-NLS-1$
|
emit("add size offset", OpCode.addI, addr, OFFSET_REF_SIZE, addr); //$NON-NLS-1$
|
||||||
return addr;
|
return addr;
|
||||||
} else {
|
} else {
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -984,7 +1040,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
emit("print character", OpCode.cout, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
|
emit("print character", OpCode.cout, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
emit("writing unknown type", OpCode.haltI, new Num(0x77726974)); //$NON-NLS-1$
|
emit("writing unknown type", OpCode.haltI, ERROR_OUTPUT_UNKNOWN_TYPE); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expr.equals(ctx.expr(ctx.expr().size() - 1)))
|
if (!expr.equals(ctx.expr(ctx.expr().size() - 1)))
|
||||||
|
|
|
@ -35,16 +35,18 @@ expr
|
||||||
| OUT PAROPEN expr (LISTDELIM expr)* PARCLOSE #write
|
| OUT PAROPEN expr (LISTDELIM expr)* PARCLOSE #write
|
||||||
| IFOPEN cond=stats IFTRUE onTrue=stats (IFFALSE onFalse=stats)? IFCLOSE #if
|
| IFOPEN cond=stats IFTRUE onTrue=stats (IFFALSE onFalse=stats)? IFCLOSE #if
|
||||||
| WHILEOPEN cond=stats WHILETRUE onTrue=stats WHILECLOSE #while
|
| WHILEOPEN cond=stats WHILETRUE onTrue=stats WHILECLOSE #while
|
||||||
| LAMBDA IDENTIFIER+ ARROW expr #lambda
|
| LAMBDA IDENTIFIER+ ARROW body=expr #lambda
|
||||||
| variable PAROPEN (expr (LISTDELIM expr)*)? PARCLOSE #call
|
| variable PAROPEN (expr (LISTDELIM expr)*)? PARCLOSE #call
|
||||||
| variable #getVariable
|
| variable #getVariable
|
||||||
|
| ARRAY PAROPEN type LISTDELIM size=expr PARCLOSE #defineArray
|
||||||
|
| ARROPEN expr (LISTDELIM expr)* ARRCLOSE #literalArray
|
||||||
| LITERAL10 #literalInteger
|
| LITERAL10 #literalInteger
|
||||||
| CHAR #literalCharacter
|
| CHAR #literalCharacter
|
||||||
| (TRUE|FALSE) #literalBoolean
|
| (TRUE|FALSE) #literalBoolean
|
||||||
;
|
;
|
||||||
|
|
||||||
type
|
type
|
||||||
: ARROPEN LITERAL10 ARRCLOSE type #typeArray
|
: type ARROPEN ARRCLOSE #typeArray
|
||||||
| type ARROW type #typeFunction
|
| type ARROW type #typeFunction
|
||||||
| staticType=(INTTYPE | BOOLTYPE | CHARTYPE) #typeSimple
|
| staticType=(INTTYPE | BOOLTYPE | CHARTYPE) #typeSimple
|
||||||
| PAROPEN (type (LISTDELIM type)*)? PARCLOSE #typeTuple
|
| PAROPEN (type (LISTDELIM type)*)? PARCLOSE #typeTuple
|
||||||
|
|
|
@ -28,10 +28,16 @@ public class ArrayTest {
|
||||||
BoppiTests.parseString("var []int arr; 0");
|
BoppiTests.parseString("var []int arr; 0");
|
||||||
assertThat(BoppiTests.log, not(empty()));
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
BoppiTests.parseString("var int a; a := 5; var [5][a]int arr; 0");
|
BoppiTests.parseString("var int[6] arr; 0");
|
||||||
assertThat(BoppiTests.log, not(empty()));
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
BoppiTests.parseString("var [4]int arr; (arr)[5]");
|
BoppiTests.parseString("var int[[]] a; 0");
|
||||||
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
|
BoppiTests.parseString("var int[] arr; (arr)[5]");
|
||||||
|
assertThat(BoppiTests.log, hasSize(1));
|
||||||
|
|
||||||
|
BoppiTests.parseString("var int[] arr; arr := array(5)");
|
||||||
assertThat(BoppiTests.log, hasSize(1));
|
assertThat(BoppiTests.log, hasSize(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,13 +58,31 @@ public class ArrayTest {
|
||||||
BoppiTests.checkString("var int a; a[5]");
|
BoppiTests.checkString("var int a; a[5]");
|
||||||
assertThat(BoppiTests.log, not(empty()));
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
BoppiTests.checkString("var [5]int arr; arr := 5");
|
BoppiTests.checkString("var int[] arr; arr := 5");
|
||||||
assertThat(BoppiTests.log, not(empty()));
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
BoppiTests.checkString("var [5]int arr; arr[4][2] := 5");
|
BoppiTests.checkString("var int[] arr; arr[4][2] := 5");
|
||||||
assertThat(BoppiTests.log, not(empty()));
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
BoppiTests.checkString("var int a; var int[5] arr; a := arr");
|
BoppiTests.checkString("var int a; var int[] arr; a := arr");
|
||||||
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
|
BoppiTests.checkString("var int[] arr; arr := array(char, 5)");
|
||||||
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
|
BoppiTests.checkString("var int[] arr; arr := ['a', 'c']");
|
||||||
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninitialized arrays
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void wrongArrayChecking2() {
|
||||||
|
BoppiTests.checkString("var int[] a; a[5]");
|
||||||
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
|
|
||||||
|
BoppiTests.checkString("var int[] a; var int[] b; a := b; a[0]");
|
||||||
assertThat(BoppiTests.log, not(empty()));
|
assertThat(BoppiTests.log, not(empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +91,11 @@ public class ArrayTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void correctArrayGeneration() {
|
public void correctArrayGeneration() {
|
||||||
|
BoppiTests.compileAndRunString("var int n; read(n); var int[] arr; arr := array(int, n); print(arr.length)", "7");
|
||||||
|
assertThat(BoppiTests.vm.getInterrupt(), is(0));
|
||||||
|
assertThat(BoppiTests.log, is(empty()));
|
||||||
|
assertThat(BoppiTests.out, is(arrayContaining("7")));
|
||||||
|
|
||||||
BoppiTests.compileAndRunFile("simpleArray.boppi");
|
BoppiTests.compileAndRunFile("simpleArray.boppi");
|
||||||
assertThat(BoppiTests.vm.getInterrupt(), is(0));
|
assertThat(BoppiTests.vm.getInterrupt(), is(0));
|
||||||
assertThat(BoppiTests.log, is(empty()));
|
assertThat(BoppiTests.log, is(empty()));
|
||||||
|
@ -84,10 +113,13 @@ public class ArrayTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void wrongArrayGeneration() {
|
public void wrongArrayGeneration() {
|
||||||
BoppiTests.compileAndRunString("var [10]int arr; arr[10] := 5");
|
BoppiTests.compileAndRunString("var int[] arr; arr := array(int, 10); arr[10] := 5");
|
||||||
assertThat(BoppiTests.vm.getInterrupt(), is(not(0)));
|
assertThat(BoppiTests.vm.getInterrupt(), is(not(0)));
|
||||||
|
|
||||||
BoppiTests.compileAndRunString("var [10]int arr; arr[-1]");
|
BoppiTests.compileAndRunString("var int[] arr; arr := array(int, 10); arr[-1]");
|
||||||
|
assertThat(BoppiTests.vm.getInterrupt(), is(not(0)));
|
||||||
|
|
||||||
|
BoppiTests.compileAndRunString("var int[] arr; arr := array(int, -1)");
|
||||||
assertThat(BoppiTests.vm.getInterrupt(), is(not(0)));
|
assertThat(BoppiTests.vm.getInterrupt(), is(not(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,33 +2,29 @@ var int i;
|
||||||
|
|
||||||
|
|
||||||
// multi-dimensional array
|
// multi-dimensional array
|
||||||
// like multi-dimensional arrays in most languages, they are arrays of (n-1)-dimensional array references, so they won't be initialised by default
|
var int[][][] arr3;
|
||||||
var [2]int arr1_1;
|
arr3 := [
|
||||||
var arr1_1 arr1_2;
|
[[1,0],
|
||||||
|
[0,1]],
|
||||||
|
[[1,1],
|
||||||
|
[0,1]],
|
||||||
|
[[3,2],
|
||||||
|
[2,3]]
|
||||||
|
];
|
||||||
|
|
||||||
var [8][2]int arr2_1;
|
arr3[0][0][0] := arr3[2][0][1] := 1337;
|
||||||
var arr2_1 arr2_2;
|
|
||||||
|
|
||||||
var [3][8][2]int arr3;
|
print(arr3[2][0][1]);
|
||||||
|
|
||||||
arr3[0] := arr2_1;
|
|
||||||
arr2_1[0] := arr1_1;
|
|
||||||
|
|
||||||
arr3[2] := arr2_2;
|
|
||||||
arr2_2[7] := arr1_2;
|
|
||||||
|
|
||||||
arr3[0][0][0] := arr3[2][7][1] := 1337;
|
|
||||||
|
|
||||||
print(arr3[2][7][1]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// array passing
|
// array passing
|
||||||
var [2][4]int target;
|
var int[][] target; target := array(int[], 2);
|
||||||
|
|
||||||
function [4]int populate(int start) {
|
function int[] populate(int start) {
|
||||||
var [4]int arr;
|
var int[] arr; arr := array(int, 4);
|
||||||
var int i; i := 0;
|
var int i; i := 0;
|
||||||
|
|
||||||
while i < 4 do
|
while i < 4 do
|
||||||
arr[i] := start+i;
|
arr[i] := start+i;
|
||||||
i := i+1;
|
i := i+1;
|
||||||
|
@ -48,7 +44,7 @@ print(target[1][3]);
|
||||||
var target target2;
|
var target target2;
|
||||||
target2 := target;
|
target2 := target;
|
||||||
|
|
||||||
var [4]int firstRow;
|
var int[] firstRow; firstRow := array(int, 4);
|
||||||
firstRow := target2[0];
|
firstRow := target2[0];
|
||||||
|
|
||||||
print(firstRow[2]);
|
print(firstRow[2]);
|
||||||
|
@ -56,13 +52,11 @@ print(firstRow[2]);
|
||||||
|
|
||||||
|
|
||||||
// function array
|
// function array
|
||||||
var [10]int arr10;
|
function int[] mapArray((int)->int f, int[] arr) {
|
||||||
|
var int[] newArr; newArr := array(int, arr.length);
|
||||||
function arr10 mapArray((int)->int f, arr10 array) {
|
|
||||||
var arr10 newArr;
|
|
||||||
var int i; i := 0;
|
var int i; i := 0;
|
||||||
while i < 10 do
|
while i < arr.length do
|
||||||
newArr[i] := f(array[i]);
|
newArr[i] := f(arr[i]);
|
||||||
i := i+1;
|
i := i+1;
|
||||||
od;
|
od;
|
||||||
newArr
|
newArr
|
||||||
|
@ -70,10 +64,10 @@ function arr10 mapArray((int)->int f, arr10 array) {
|
||||||
|
|
||||||
function int increment(int a) a+1;
|
function int increment(int a) a+1;
|
||||||
|
|
||||||
var arr10 myArray;
|
var int[] myArray; myArray := array(int, 9);
|
||||||
|
|
||||||
i := 0;
|
i := 0;
|
||||||
while i < 10 do
|
while i < myArray.length do
|
||||||
myArray[i] := i*i+10;
|
myArray[i] := i*i+10;
|
||||||
i := i+1;
|
i := i+1;
|
||||||
od;
|
od;
|
||||||
|
|
|
@ -1,46 +1,36 @@
|
||||||
//Recursive fibonacci with memoization closure
|
//Recursive fibonacci with memoization closure
|
||||||
|
|
||||||
var int n;
|
function (int)->int memoizedFib() {
|
||||||
|
var int[] memo;
|
||||||
|
memo := array(int, 50);
|
||||||
|
|
||||||
var (int)->int fib;
|
function int fib(int n) {
|
||||||
|
|
||||||
function fib memoize(fib f) {
|
|
||||||
var [50]int memo;
|
|
||||||
|
|
||||||
var int i; i := 0; while i < 50 do
|
|
||||||
memo[i] := 0;
|
|
||||||
i := i+1;
|
|
||||||
od;
|
|
||||||
|
|
||||||
function int memoFib(int n) {
|
|
||||||
if n >= 0 && n < 50 then
|
|
||||||
if memo[n] > 0 then
|
|
||||||
memo[n]
|
|
||||||
else
|
|
||||||
memo[n] := f(n)
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
f(n)
|
|
||||||
fi
|
|
||||||
};
|
|
||||||
|
|
||||||
memoFib
|
|
||||||
};
|
|
||||||
|
|
||||||
function int fib_(int n) {
|
|
||||||
if n < 2 then
|
if n < 2 then
|
||||||
1
|
1
|
||||||
else
|
else
|
||||||
fib(n-1)+fib(n-2) //has to call `fib` instead of `fib_` because `fib_` is constant
|
if memo[n] > 0 then
|
||||||
|
memo[n]
|
||||||
|
else
|
||||||
|
var int answer;
|
||||||
|
answer := fib(n-1)+fib(n-2);
|
||||||
|
|
||||||
|
if n < memo.length then
|
||||||
|
memo[n] := answer
|
||||||
|
fi;
|
||||||
|
|
||||||
|
answer
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
};
|
};
|
||||||
|
fib
|
||||||
|
};
|
||||||
|
|
||||||
fib := memoize(fib_);
|
var (int)->int myFib;
|
||||||
|
myFib := memoizedFib();
|
||||||
|
|
||||||
|
var int n;
|
||||||
read(n);
|
read(n);
|
||||||
|
|
||||||
while n > 0 do
|
while n > 0 do
|
||||||
print(fib(n));
|
print(myFib(n));
|
||||||
read(n)
|
read(n)
|
||||||
od;
|
od;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
var [5]int arr;
|
var int[] arr; arr := array(int, 5);
|
||||||
|
|
||||||
var int i; i := 0;
|
var int i; i := 0;
|
||||||
|
|
||||||
|
@ -11,13 +11,11 @@ print(arr[3]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var [2]char arr2;
|
var char[] arr2; arr2 := ['H', 'a'];
|
||||||
arr2[0] := 'H';
|
|
||||||
arr2[1] := 'a';
|
|
||||||
|
|
||||||
print(arr2[0], arr2[1]);
|
print(arr2[0], arr2[1]);
|
||||||
|
|
||||||
var [2]char arr3;
|
var char[] arr3; arr3 := array(char, 2);
|
||||||
arr3[1] := 'a';
|
arr3[1] := 'a';
|
||||||
arr3[0] := 'H';
|
arr3[0] := 'H';
|
||||||
|
|
||||||
|
|
|
@ -3,33 +3,24 @@ package pp.s1184725.boppi.type;
|
||||||
import pp.iloc.eval.Machine;
|
import pp.iloc.eval.Machine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vector type of fixed size. Takes a length and a type parameter.
|
* A vector type of run-time defined size. Takes a type parameter.
|
||||||
*
|
*
|
||||||
* @author Frank Wibbelink
|
* @author Frank Wibbelink
|
||||||
*/
|
*/
|
||||||
public class ArrayType implements ReferenceType {
|
public class ArrayType implements ReferenceType {
|
||||||
private int count;
|
|
||||||
private Type elType;
|
private Type elType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new array type with the given number of elements and their
|
* Creates a new array type with the given number of elements and their
|
||||||
* type.
|
* type.
|
||||||
*
|
*
|
||||||
* @param count
|
|
||||||
* the number of elements
|
|
||||||
* @param type
|
* @param type
|
||||||
* the type of elements
|
* the type of elements
|
||||||
*/
|
*/
|
||||||
public ArrayType(int count, Type type) {
|
public ArrayType(Type type) {
|
||||||
this.count = count;
|
|
||||||
this.elType = type;
|
this.elType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getReferenceSize() {
|
|
||||||
return count * elType.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return Machine.INT_SIZE;
|
return Machine.INT_SIZE;
|
||||||
|
@ -41,12 +32,12 @@ public class ArrayType implements ReferenceType {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ArrayType other = (ArrayType) obj;
|
ArrayType other = (ArrayType) obj;
|
||||||
return count == other.count && elType.equals(other.elType);
|
return elType.equals(other.elType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return elType.toString()+"["+count+"]";
|
return elType.toString()+"[]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,7 +28,11 @@ public class FunctionType implements ReferenceType {
|
||||||
return Machine.INT_SIZE;
|
return Machine.INT_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Returns the size of the function context.
|
||||||
|
*
|
||||||
|
* @return the size (in bytes) of the function context
|
||||||
|
*/
|
||||||
public int getReferenceSize() {
|
public int getReferenceSize() {
|
||||||
return 3 * Machine.INT_SIZE;
|
return 3 * Machine.INT_SIZE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,4 @@ package pp.s1184725.boppi.type;
|
||||||
* @author Frank Wibbelink
|
* @author Frank Wibbelink
|
||||||
*/
|
*/
|
||||||
public interface ReferenceType extends Type {
|
public interface ReferenceType extends Type {
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the size of the object this type references.
|
|
||||||
* @return the size (in bytes) of the referenced object
|
|
||||||
*/
|
|
||||||
public int getReferenceSize();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue