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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
public Type visit(ParseTree 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()));
|
||||
var.setConstant(ctx.CONSTANT() != null);
|
||||
an.variables.put(ctx, var);
|
||||
an.variableRoot.put(var, ctx.getParent());
|
||||
an.variableRoot.put(var, ctx.getParent().getParent());
|
||||
|
||||
if (var.getType() instanceof TupleType)
|
||||
log.severe(getError(ctx, Messages.getString("BoppiChecker.4"), //$NON-NLS-1$
|
||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.BOOLTYPE),
|
||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.CHARTYPE),
|
||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.INTTYPE)));
|
||||
|
||||
if (var.getType() instanceof ReferenceType)
|
||||
var.assign();
|
||||
} catch (SymbolTableException e) {
|
||||
log.severe(getError(ctx, e.getMessage()));
|
||||
}
|
||||
|
@ -200,6 +205,13 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
return SimpleType.VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type visitDefineArray(DefineArrayContext ctx) {
|
||||
checkConstraint(visit(ctx.size), SimpleType.INT, ctx);
|
||||
|
||||
return new ArrayType(visit(ctx.type()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type visitGetVariable(GetVariableContext ctx) {
|
||||
return visit(ctx.variable());
|
||||
|
@ -301,6 +313,16 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
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
|
||||
public Type visitLiteralBoolean(LiteralBooleanContext ctx) {
|
||||
return SimpleType.BOOL;
|
||||
|
@ -390,15 +412,7 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
|
||||
@Override
|
||||
public Type visitTypeArray(TypeArrayContext ctx) {
|
||||
int size = 0;
|
||||
|
||||
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()));
|
||||
return new ArrayType(visit(ctx.type()));
|
||||
}
|
||||
|
||||
@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_FUNCREF_ARP = new Num(4), OFFSET_FUNCREF_ARSIZE = new Num(8), OFFSET_REF_COUNT = new Num(-8),
|
||||
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 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:
|
||||
* <ol>
|
||||
|
@ -570,7 +563,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
*/
|
||||
@Override
|
||||
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$
|
||||
|
||||
Label skip = makeLabel("s"); //$NON-NLS-1$
|
||||
|
@ -579,7 +572,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
|
||||
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$
|
||||
|
||||
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$
|
||||
|
||||
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 + "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$
|
||||
|
@ -622,6 +615,32 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
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
|
||||
public Reg visitGetVariable(GetVariableContext ctx) {
|
||||
Type type = an.types.get(ctx);
|
||||
|
@ -635,6 +654,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -717,9 +745,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
|
||||
return regPool.withReg((i, temp1) -> {
|
||||
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("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());
|
||||
}
|
||||
|
||||
@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
|
||||
public Reg visitLiteralBoolean(LiteralBooleanContext ctx) {
|
||||
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$
|
||||
});
|
||||
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;
|
||||
|
@ -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.and, r1, r2, r2); //$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$
|
||||
offset);
|
||||
|
@ -914,8 +968,10 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
Type innerType = an.types.get(ctx.variable());
|
||||
Reg addr = visit(ctx.variable());
|
||||
|
||||
emit("get object address", OpCode.load, addr, addr); //$NON-NLS-1$
|
||||
|
||||
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;
|
||||
} else {
|
||||
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$
|
||||
});
|
||||
} 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)))
|
||||
|
|
|
@ -35,16 +35,18 @@ expr
|
|||
| OUT PAROPEN expr (LISTDELIM expr)* PARCLOSE #write
|
||||
| IFOPEN cond=stats IFTRUE onTrue=stats (IFFALSE onFalse=stats)? IFCLOSE #if
|
||||
| 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 #getVariable
|
||||
| ARRAY PAROPEN type LISTDELIM size=expr PARCLOSE #defineArray
|
||||
| ARROPEN expr (LISTDELIM expr)* ARRCLOSE #literalArray
|
||||
| LITERAL10 #literalInteger
|
||||
| CHAR #literalCharacter
|
||||
| (TRUE|FALSE) #literalBoolean
|
||||
;
|
||||
|
||||
type
|
||||
: ARROPEN LITERAL10 ARRCLOSE type #typeArray
|
||||
: type ARROPEN ARRCLOSE #typeArray
|
||||
| type ARROW type #typeFunction
|
||||
| staticType=(INTTYPE | BOOLTYPE | CHARTYPE) #typeSimple
|
||||
| PAROPEN (type (LISTDELIM type)*)? PARCLOSE #typeTuple
|
||||
|
|
|
@ -28,10 +28,16 @@ public class ArrayTest {
|
|||
BoppiTests.parseString("var []int arr; 0");
|
||||
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()));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -52,13 +58,31 @@ public class ArrayTest {
|
|||
BoppiTests.checkString("var int a; a[5]");
|
||||
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()));
|
||||
|
||||
BoppiTests.checkString("var [5]int arr; arr[4][2] := 5");
|
||||
BoppiTests.checkString("var int[] arr; arr[4][2] := 5");
|
||||
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()));
|
||||
}
|
||||
|
||||
|
@ -67,6 +91,11 @@ public class ArrayTest {
|
|||
*/
|
||||
@Test
|
||||
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");
|
||||
assertThat(BoppiTests.vm.getInterrupt(), is(0));
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
@ -84,10 +113,13 @@ public class ArrayTest {
|
|||
*/
|
||||
@Test
|
||||
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)));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,33 +2,29 @@ var int i;
|
|||
|
||||
|
||||
// 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 [2]int arr1_1;
|
||||
var arr1_1 arr1_2;
|
||||
var int[][][] arr3;
|
||||
arr3 := [
|
||||
[[1,0],
|
||||
[0,1]],
|
||||
[[1,1],
|
||||
[0,1]],
|
||||
[[3,2],
|
||||
[2,3]]
|
||||
];
|
||||
|
||||
var [8][2]int arr2_1;
|
||||
var arr2_1 arr2_2;
|
||||
arr3[0][0][0] := arr3[2][0][1] := 1337;
|
||||
|
||||
var [3][8][2]int arr3;
|
||||
|
||||
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]);
|
||||
print(arr3[2][0][1]);
|
||||
|
||||
|
||||
|
||||
// array passing
|
||||
var [2][4]int target;
|
||||
var int[][] target; target := array(int[], 2);
|
||||
|
||||
function [4]int populate(int start) {
|
||||
var [4]int arr;
|
||||
function int[] populate(int start) {
|
||||
var int[] arr; arr := array(int, 4);
|
||||
var int i; i := 0;
|
||||
|
||||
while i < 4 do
|
||||
arr[i] := start+i;
|
||||
i := i+1;
|
||||
|
@ -48,7 +44,7 @@ print(target[1][3]);
|
|||
var target target2;
|
||||
target2 := target;
|
||||
|
||||
var [4]int firstRow;
|
||||
var int[] firstRow; firstRow := array(int, 4);
|
||||
firstRow := target2[0];
|
||||
|
||||
print(firstRow[2]);
|
||||
|
@ -56,13 +52,11 @@ print(firstRow[2]);
|
|||
|
||||
|
||||
// function array
|
||||
var [10]int arr10;
|
||||
|
||||
function arr10 mapArray((int)->int f, arr10 array) {
|
||||
var arr10 newArr;
|
||||
function int[] mapArray((int)->int f, int[] arr) {
|
||||
var int[] newArr; newArr := array(int, arr.length);
|
||||
var int i; i := 0;
|
||||
while i < 10 do
|
||||
newArr[i] := f(array[i]);
|
||||
while i < arr.length do
|
||||
newArr[i] := f(arr[i]);
|
||||
i := i+1;
|
||||
od;
|
||||
newArr
|
||||
|
@ -70,10 +64,10 @@ function arr10 mapArray((int)->int f, arr10 array) {
|
|||
|
||||
function int increment(int a) a+1;
|
||||
|
||||
var arr10 myArray;
|
||||
var int[] myArray; myArray := array(int, 9);
|
||||
|
||||
i := 0;
|
||||
while i < 10 do
|
||||
while i < myArray.length do
|
||||
myArray[i] := i*i+10;
|
||||
i := i+1;
|
||||
od;
|
||||
|
|
|
@ -1,46 +1,36 @@
|
|||
//Recursive fibonacci with memoization closure
|
||||
|
||||
var int n;
|
||||
function (int)->int memoizedFib() {
|
||||
var int[] memo;
|
||||
memo := array(int, 50);
|
||||
|
||||
var (int)->int fib;
|
||||
|
||||
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) {
|
||||
function int fib(int n) {
|
||||
if n < 2 then
|
||||
1
|
||||
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
|
||||
};
|
||||
fib
|
||||
};
|
||||
|
||||
fib := memoize(fib_);
|
||||
|
||||
var (int)->int myFib;
|
||||
myFib := memoizedFib();
|
||||
|
||||
var int n;
|
||||
read(n);
|
||||
|
||||
while n > 0 do
|
||||
print(fib(n));
|
||||
print(myFib(n));
|
||||
read(n)
|
||||
od;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var [5]int arr;
|
||||
var int[] arr; arr := array(int, 5);
|
||||
|
||||
var int i; i := 0;
|
||||
|
||||
|
@ -11,13 +11,11 @@ print(arr[3]);
|
|||
|
||||
|
||||
|
||||
var [2]char arr2;
|
||||
arr2[0] := 'H';
|
||||
arr2[1] := 'a';
|
||||
var char[] arr2; arr2 := ['H', 'a'];
|
||||
|
||||
print(arr2[0], arr2[1]);
|
||||
|
||||
var [2]char arr3;
|
||||
var char[] arr3; arr3 := array(char, 2);
|
||||
arr3[1] := 'a';
|
||||
arr3[0] := 'H';
|
||||
|
||||
|
|
|
@ -3,33 +3,24 @@ package pp.s1184725.boppi.type;
|
|||
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
|
||||
*/
|
||||
public class ArrayType implements ReferenceType {
|
||||
private int count;
|
||||
private Type elType;
|
||||
|
||||
/**
|
||||
* Creates a new array type with the given number of elements and their
|
||||
* type.
|
||||
*
|
||||
* @param count
|
||||
* the number of elements
|
||||
* @param type
|
||||
* the type of elements
|
||||
*/
|
||||
public ArrayType(int count, Type type) {
|
||||
this.count = count;
|
||||
public ArrayType(Type type) {
|
||||
this.elType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReferenceSize() {
|
||||
return count * elType.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return Machine.INT_SIZE;
|
||||
|
@ -41,12 +32,12 @@ public class ArrayType implements ReferenceType {
|
|||
return false;
|
||||
|
||||
ArrayType other = (ArrayType) obj;
|
||||
return count == other.count && elType.equals(other.elType);
|
||||
return elType.equals(other.elType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return elType.toString()+"["+count+"]";
|
||||
return elType.toString()+"[]";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,9 +28,13 @@ public class FunctionType implements ReferenceType {
|
|||
return Machine.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Returns the size of the function context.
|
||||
*
|
||||
* @return the size (in bytes) of the function context
|
||||
*/
|
||||
public int getReferenceSize() {
|
||||
return 3*Machine.INT_SIZE;
|
||||
return 3 * Machine.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,10 +6,4 @@ package pp.s1184725.boppi.type;
|
|||
* @author Frank Wibbelink
|
||||
*/
|
||||
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