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,9 +28,13 @@ 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;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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