removed lambdas, added string I/O, improved tests, malloc zeroes memory
This commit is contained in:
		
							parent
							
								
									12d878d24b
								
							
						
					
					
						commit
						c8c13e5d96
					
				| 
						 | 
					@ -283,36 +283,6 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
 | 
				
			||||||
		return SimpleType.BOOL;
 | 
							return SimpleType.BOOL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
					 | 
				
			||||||
	public Type visitLambda(LambdaContext ctx) {
 | 
					 | 
				
			||||||
		// try {
 | 
					 | 
				
			||||||
		// TupleType parameterTypes = new TupleType(
 | 
					 | 
				
			||||||
		// ctx.type().stream().skip(1).map(this::visit).collect(Collectors.toList()));
 | 
					 | 
				
			||||||
		// FunctionType type = new FunctionType(visit(ctx.result),
 | 
					 | 
				
			||||||
		// parameterTypes);
 | 
					 | 
				
			||||||
		// Variable<Type> func = an.symbols.put(ctx.name.getText(), type);
 | 
					 | 
				
			||||||
		// an.variables.put(ctx, func);
 | 
					 | 
				
			||||||
		//
 | 
					 | 
				
			||||||
		// an.function.put(ctx, an.symbols.withFunctionScope(() -> {
 | 
					 | 
				
			||||||
		// for (int i = 1; i < ctx.type().size(); i++)
 | 
					 | 
				
			||||||
		// try {
 | 
					 | 
				
			||||||
		// an.symbols.put(ctx.IDENTIFIER(i).getText(),
 | 
					 | 
				
			||||||
		// an.types.get(ctx.type(i)));
 | 
					 | 
				
			||||||
		// } catch (SymbolTableException e) {
 | 
					 | 
				
			||||||
		// log.severe(getError(ctx, e.getMessage()));
 | 
					 | 
				
			||||||
		// }
 | 
					 | 
				
			||||||
		//
 | 
					 | 
				
			||||||
		// checkConstraint(an.symbols.withScope(() -> visit(ctx.body)),
 | 
					 | 
				
			||||||
		// an.types.get(ctx.result), ctx);
 | 
					 | 
				
			||||||
		// }));
 | 
					 | 
				
			||||||
		// } catch (SymbolTableException e) {
 | 
					 | 
				
			||||||
		// log.severe(getError(ctx, e.getMessage()));
 | 
					 | 
				
			||||||
		// }
 | 
					 | 
				
			||||||
		log.severe("Lambda not yet implemented"); //$NON-NLS-1$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return SimpleType.VOID;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public Type visitLiteralArray(LiteralArrayContext ctx) {
 | 
						public Type visitLiteralArray(LiteralArrayContext ctx) {
 | 
				
			||||||
		Type elementType = visit(ctx.expr(0));
 | 
							Type elementType = visit(ctx.expr(0));
 | 
				
			||||||
| 
						 | 
					@ -320,6 +290,9 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
 | 
				
			||||||
		for (int i = 1; i < ctx.expr().size(); i++)
 | 
							for (int i = 1; i < ctx.expr().size(); i++)
 | 
				
			||||||
			checkConstraint(visit(ctx.expr(i)), elementType, ctx);
 | 
								checkConstraint(visit(ctx.expr(i)), elementType, ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (SimpleType.VOID.equals(elementType))
 | 
				
			||||||
 | 
								log.severe(getError(ctx, Messages.getString("BoppiChecker.16"))); //$NON-NLS-1$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return new ArrayType(elementType);
 | 
							return new ArrayType(elementType);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -623,11 +623,11 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
				
			||||||
		emit("produce array size", OpCode.multI, arrSize, new Num(elementType.getSize()), arrSize); //$NON-NLS-1$
 | 
							emit("produce array size", OpCode.multI, arrSize, new Num(elementType.getSize()), arrSize); //$NON-NLS-1$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return regPool.blockReg(arrSize, () -> regPool.withReg((temp) -> {
 | 
							return regPool.blockReg(arrSize, () -> regPool.withReg((temp) -> {
 | 
				
			||||||
			Label validSize = makeLabel("aszt"), invalidSize = makeLabel("aszf");
 | 
								Label validSize = makeLabel("aszt"), invalidSize = makeLabel("aszf"); //$NON-NLS-1$ //$NON-NLS-2$
 | 
				
			||||||
			emit("check size non negative", OpCode.cmp_GE, arrSize, RegisterPool.ZERO, temp);
 | 
								emit("check size non negative", OpCode.cmp_GE, arrSize, RegisterPool.ZERO, temp); //$NON-NLS-1$
 | 
				
			||||||
			emit("", OpCode.cbr, temp, validSize, invalidSize);
 | 
								emit("", OpCode.cbr, temp, validSize, invalidSize); //$NON-NLS-1$
 | 
				
			||||||
			emit("invalid array size", invalidSize, OpCode.haltI, ERROR_ILLEGAL_ARRAY_SIZE);
 | 
								emit("invalid array size", invalidSize, OpCode.haltI, ERROR_ILLEGAL_ARRAY_SIZE); //$NON-NLS-1$
 | 
				
			||||||
			emit("valid array size", validSize, OpCode.nop);
 | 
								emit("valid array size", validSize, OpCode.nop); //$NON-NLS-1$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			malloc(temp, arrSize);
 | 
								malloc(temp, arrSize);
 | 
				
			||||||
		}));
 | 
							}));
 | 
				
			||||||
| 
						 | 
					@ -768,6 +768,9 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
				
			||||||
						emit("loop or break", OpCode.cbr, temp1, cond, end); //$NON-NLS-1$
 | 
											emit("loop or break", OpCode.cbr, temp1, cond, end); //$NON-NLS-1$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						emit("end equality check", end, OpCode.nop); //$NON-NLS-1$
 | 
											emit("end equality check", end, OpCode.nop); //$NON-NLS-1$
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											if (ops.get(ctx.op.getType()).equals(OpCode.cmp_NE))
 | 
				
			||||||
 | 
												emit("invert equality", OpCode.cmp_EQ, temp1, RegisterPool.ZERO, temp1); //$NON-NLS-1$
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					@ -794,13 +797,6 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
				
			||||||
		return lhs;
 | 
							return lhs;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
					 | 
				
			||||||
	public Reg visitLambda(LambdaContext ctx) {
 | 
					 | 
				
			||||||
		emit(ctx.getText(), OpCode.haltI, new Num(768));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return visit(ctx.expr());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public Reg visitLiteralArray(LiteralArrayContext ctx) {
 | 
						public Reg visitLiteralArray(LiteralArrayContext ctx) {
 | 
				
			||||||
		int elements = ctx.expr().size();
 | 
							int elements = ctx.expr().size();
 | 
				
			||||||
| 
						 | 
					@ -905,6 +901,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
				
			||||||
					Reg addr = visit(expr);
 | 
										Reg addr = visit(expr);
 | 
				
			||||||
					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 if (an.types.get(expr) instanceof ArrayType && SimpleType.CHAR.equals(((ArrayType)an.types.get(expr)).getType()))
 | 
				
			||||||
 | 
									res = regPool.withReg((temp) -> {
 | 
				
			||||||
 | 
										emit("call stdsin", OpCode.loadI, new Num(prog.size() + 3), temp); //$NON-NLS-1$
 | 
				
			||||||
 | 
										emit("call stdsin", OpCode.push, temp); //$NON-NLS-1$
 | 
				
			||||||
 | 
										emit("call stdsin", OpCode.jumpI, new Label("stdsin")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
				
			||||||
 | 
										emit("get address", OpCode.pop, temp); //$NON-NLS-1$
 | 
				
			||||||
 | 
										Reg addr = visit(expr);
 | 
				
			||||||
 | 
										emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				emit("reading unknown type", OpCode.haltI, ERROR_INPUT_UNKNOWN_TYPE); //$NON-NLS-1$
 | 
									emit("reading unknown type", OpCode.haltI, ERROR_INPUT_UNKNOWN_TYPE); //$NON-NLS-1$
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1025,7 +1030,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (SimpleType.BOOL.equals(type)) {
 | 
									if (SimpleType.BOOL.equals(type)) {
 | 
				
			||||||
					regPool.withReg((temp) -> {
 | 
										regPool.withReg((temp) -> {
 | 
				
			||||||
						emit("call stdbout", OpCode.loadI, new Num(prog.size() + 4), temp); // $NON-NLS-2$ //$NON-NLS-1$
 | 
											emit("call stdbout", OpCode.loadI, new Num(prog.size() + 4), temp); //$NON-NLS-1$
 | 
				
			||||||
						emit("call stdbout", OpCode.push, temp); //$NON-NLS-1$
 | 
											emit("call stdbout", OpCode.push, temp); //$NON-NLS-1$
 | 
				
			||||||
						emit("call stdbout", OpCode.push, result); //$NON-NLS-1$
 | 
											emit("call stdbout", OpCode.push, result); //$NON-NLS-1$
 | 
				
			||||||
						emit("call stdbout", OpCode.jumpI, new Label("stdbout")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
											emit("call stdbout", OpCode.jumpI, new Label("stdbout")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
				
			||||||
| 
						 | 
					@ -1039,6 +1044,13 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
				
			||||||
						emit("push 1", OpCode.push, temp); //$NON-NLS-1$
 | 
											emit("push 1", OpCode.push, temp); //$NON-NLS-1$
 | 
				
			||||||
						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 if (type instanceof ArrayType && SimpleType.CHAR.equals(((ArrayType)type).getType())) {
 | 
				
			||||||
 | 
										regPool.withReg((temp) -> {
 | 
				
			||||||
 | 
											emit("call stdsout", OpCode.loadI, new Num(prog.size() + 4), temp); //$NON-NLS-1$
 | 
				
			||||||
 | 
											emit("call stdsout", OpCode.push, temp); //$NON-NLS-1$
 | 
				
			||||||
 | 
											emit("call stdsout", OpCode.push, result); //$NON-NLS-1$
 | 
				
			||||||
 | 
											emit("call stdsout", OpCode.jumpI, new Label("stdsout")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					emit("writing unknown type", OpCode.haltI, ERROR_OUTPUT_UNKNOWN_TYPE); //$NON-NLS-1$
 | 
										emit("writing unknown type", OpCode.haltI, ERROR_OUTPUT_UNKNOWN_TYPE); //$NON-NLS-1$
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,6 @@ 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 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
 | 
						| ARRAY PAROPEN type LISTDELIM size=expr PARCLOSE #defineArray
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,6 +70,10 @@ ma_final: storeAI  m_n => m_p,@off_next          // link previous free slot to n
 | 
				
			||||||
          loadI    1 => m_1
 | 
					          loadI    1 => m_1
 | 
				
			||||||
          storeAI  m_1 => m_c,@off_oref          // set reference count to 1
 | 
					          storeAI  m_1 => m_c,@off_oref          // set reference count to 1
 | 
				
			||||||
          storeAI  m_s => m_c,@off_osize         // set object size
 | 
					          storeAI  m_s => m_c,@off_osize         // set object size
 | 
				
			||||||
 | 
					ma_zerc:  cbr      m_s -> ma_zerl,ma_null        // zero memory
 | 
				
			||||||
 | 
					ma_zerl:  subI     m_s,1 => m_s
 | 
				
			||||||
 | 
					          cstoreAO m_0 => m_c,m_s
 | 
				
			||||||
 | 
					          jumpI -> ma_zerc
 | 
				
			||||||
ma_null:  pop      => m_1                        // load return address
 | 
					ma_null:  pop      => m_1                        // load return address
 | 
				
			||||||
          push     m_c                           // store object address
 | 
					          push     m_c                           // store object address
 | 
				
			||||||
          jump -> m_1
 | 
					          jump -> m_1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ BoppiChecker.12=Cannot print argument of type '%s'.
 | 
				
			||||||
BoppiChecker.13=Constant '%s' may already be assigned.
 | 
					BoppiChecker.13=Constant '%s' may already be assigned.
 | 
				
			||||||
BoppiChecker.14=Variable '%s' may not be assigned.
 | 
					BoppiChecker.14=Variable '%s' may not be assigned.
 | 
				
			||||||
BoppiChecker.15=Variable '%s' is not assigned.
 | 
					BoppiChecker.15=Variable '%s' is not assigned.
 | 
				
			||||||
 | 
					BoppiChecker.16=Cannot make array of void elements
 | 
				
			||||||
BoppiChecker.2=Expected %d arguments but got %d.
 | 
					BoppiChecker.2=Expected %d arguments but got %d.
 | 
				
			||||||
BoppiChecker.3='%s' is not a function.
 | 
					BoppiChecker.3='%s' is not a function.
 | 
				
			||||||
BoppiChecker.4=Variable must have a type %s, %s, %s or function.
 | 
					BoppiChecker.4=Variable must have a type %s, %s, %s or function.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,22 @@ sbout_e: pop => m_1                 // load return address
 | 
				
			||||||
         jump -> m_1
 | 
					         jump -> m_1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// write an array of characters (a string) to output
 | 
				
			||||||
 | 
					// stack: [return address, address] -> []
 | 
				
			||||||
 | 
					stdsout: pop => m_1                   // get address
 | 
				
			||||||
 | 
					         loadAI m_1,@off_osize => m_2 // get length
 | 
				
			||||||
 | 
					sout_lc: cbr m_2 -> sout_ll,sout_le   // check if any character to push
 | 
				
			||||||
 | 
					sout_ll: subI m_2, 1 => m_2           // iterate backward
 | 
				
			||||||
 | 
					         cloadAO m_1, m_2 => m_c      // get character
 | 
				
			||||||
 | 
					         cpush m_c                    // push character
 | 
				
			||||||
 | 
					         jumpI -> sout_lc             // repeat
 | 
				
			||||||
 | 
					sout_le: loadAI m_1,@off_osize => m_2 // get length
 | 
				
			||||||
 | 
					         push m_2                     // push string length
 | 
				
			||||||
 | 
					         cout ""                      // print string
 | 
				
			||||||
 | 
					         pop => m_1                   // get return address
 | 
				
			||||||
 | 
					         jump -> m_1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// read a character from input
 | 
					// read a character from input
 | 
				
			||||||
// stack: [return address] -> [char]
 | 
					// stack: [return address] -> [char]
 | 
				
			||||||
stdcin:  cin ""                     // get line
 | 
					stdcin:  cin ""                     // get line
 | 
				
			||||||
| 
						 | 
					@ -35,5 +51,32 @@ scin_le: loadI 0 => m_0             // reset zero register
 | 
				
			||||||
         cpush m_2                  // push result character
 | 
					         cpush m_2                  // push result character
 | 
				
			||||||
         jump -> m_1
 | 
					         jump -> m_1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// read an array of characters (a string) from input
 | 
				
			||||||
 | 
					// the memalloc label cannot be used, so address 28 is used instead
 | 
				
			||||||
 | 
					// stack: [return address] -> [address]
 | 
				
			||||||
 | 
					stdsin:  cin ""                     // get line
 | 
				
			||||||
 | 
					         pop => m_2                 // get length
 | 
				
			||||||
 | 
					         push m_2                   // save length
 | 
				
			||||||
 | 
					         loadI #ssin_a => m_1       // call malloc
 | 
				
			||||||
 | 
					         push m_1                   // call malloc
 | 
				
			||||||
 | 
					         push m_2                   // call malloc
 | 
				
			||||||
 | 
					         loadI 28 => m_c            // call malloc
 | 
				
			||||||
 | 
					         jump -> m_c                // call malloc
 | 
				
			||||||
 | 
					ssin_a:  pop => m_1                 // get array address
 | 
				
			||||||
 | 
					         pop => m_2                 // get length
 | 
				
			||||||
 | 
					         i2i m_1 => m_n             // load character iterator
 | 
				
			||||||
 | 
					ssin_c:  cbr m_2 -> ssin_l, ssin_e  // pop characters into the array
 | 
				
			||||||
 | 
					ssin_l:  subI m_2,1 => m_2
 | 
				
			||||||
 | 
					         cpop => m_c                // pop character
 | 
				
			||||||
 | 
					         cstore m_c => m_n          // save character
 | 
				
			||||||
 | 
					         addI m_n,1 => m_n          // increment iterator
 | 
				
			||||||
 | 
					         jumpI -> ssin_c
 | 
				
			||||||
 | 
					ssin_e:  pop => m_2                 // get return address
 | 
				
			||||||
 | 
					         push m_1                   // push array address
 | 
				
			||||||
 | 
					         jump -> m_2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
estdlib_: nop
 | 
					estdlib_: nop
 | 
				
			||||||
// end of stdlib
 | 
					// end of stdlib
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,20 @@ public class ArrayTest {
 | 
				
			||||||
		assertThat(BoppiTests.log, is(empty()));
 | 
							assertThat(BoppiTests.log, is(empty()));
 | 
				
			||||||
		assertThat(BoppiTests.out, is(arrayContaining("1337", "13", "2", "15")));
 | 
							assertThat(BoppiTests.out, is(arrayContaining("1337", "13", "2", "15")));
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							BoppiTests.compileAndRunString("var int[][] m; m := [[1,3]]; m[0]; var int[] a; a := [8,9]; print(m[0][1])");
 | 
				
			||||||
 | 
							assertThat(BoppiTests.vm.getInterrupt(), is(0));
 | 
				
			||||||
 | 
							assertThat(BoppiTests.log, is(empty()));
 | 
				
			||||||
 | 
							assertThat(BoppiTests.out, is(arrayContaining("3")));
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							BoppiTests.compileAndRunString("print([1,2]==[1,2],[1,2]<>[1,2],[1]==[1,2],[0]<>[2])");
 | 
				
			||||||
 | 
							assertThat(BoppiTests.vm.getInterrupt(), is(0));
 | 
				
			||||||
 | 
							assertThat(BoppiTests.log, is(empty()));
 | 
				
			||||||
 | 
							assertThat(BoppiTests.out, is(arrayContaining("true", "false", "false", "true")));
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							BoppiTests.compileAndRunFile("arrayFunctions.boppi", "Hello");
 | 
				
			||||||
 | 
							assertThat(BoppiTests.vm.getInterrupt(), is(0));
 | 
				
			||||||
 | 
							assertThat(BoppiTests.log, is(empty()));
 | 
				
			||||||
 | 
							assertThat(BoppiTests.out, is(arrayContaining("Hi;Hello;1337")));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,72 @@
 | 
				
			||||||
 | 
					function char[] concat(char[] a, char[] b) {
 | 
				
			||||||
 | 
					    var char[] result; result := array(char, a.length+b.length);
 | 
				
			||||||
 | 
					    var int i; i := 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while i < result.length do
 | 
				
			||||||
 | 
					        result[i] := if i < a.length then a[i] else b[i-a.length] fi;
 | 
				
			||||||
 | 
					        i := i+1;
 | 
				
			||||||
 | 
					    od;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function char[] substring(char[] s, int start, int stop) {
 | 
				
			||||||
 | 
					    var char[] result; result := array(char, stop-start);
 | 
				
			||||||
 | 
					    var int i; i := 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while i < result.length do
 | 
				
			||||||
 | 
					        result[i] := s[i+start];
 | 
				
			||||||
 | 
					        i := i+1;
 | 
				
			||||||
 | 
					    od;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function char dtoa(int d) {
 | 
				
			||||||
 | 
					    var char c;    c := '0';
 | 
				
			||||||
 | 
					    if d == 1 then c := '1' fi;
 | 
				
			||||||
 | 
					    if d == 2 then c := '2' fi;
 | 
				
			||||||
 | 
					    if d == 3 then c := '3' fi;
 | 
				
			||||||
 | 
					    if d == 4 then c := '4' fi;
 | 
				
			||||||
 | 
					    if d == 5 then c := '5' fi;
 | 
				
			||||||
 | 
					    if d == 6 then c := '6' fi;
 | 
				
			||||||
 | 
					    if d == 7 then c := '7' fi;
 | 
				
			||||||
 | 
					    if d == 8 then c := '8' fi;
 | 
				
			||||||
 | 
					    if d == 9 then c := '9' fi;
 | 
				
			||||||
 | 
					    c
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function char[] itoa(int n) {
 | 
				
			||||||
 | 
					    if n == 0 then
 | 
				
			||||||
 | 
					        ['0']
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        if n < 0 then
 | 
				
			||||||
 | 
					            concat(['-'], itoa(-n))
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            if n >= 10 then
 | 
				
			||||||
 | 
					                concat(itoa(n/10), [dtoa(n-n/10*10)])
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                [dtoa(n)]
 | 
				
			||||||
 | 
					            fi
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function char[] strjoin(char[][] strings, char[] sep) {
 | 
				
			||||||
 | 
					    var char[] result; result := array(char, 0);
 | 
				
			||||||
 | 
					    var int i; i := 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while i < strings.length do
 | 
				
			||||||
 | 
					        result := concat(result, strings[i]);
 | 
				
			||||||
 | 
					        if i < strings.length-1 then
 | 
				
			||||||
 | 
					            result := concat(result, sep);
 | 
				
			||||||
 | 
					        fi;
 | 
				
			||||||
 | 
					        i := i+1;
 | 
				
			||||||
 | 
					    od;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var char[] input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print(strjoin([['H','i'], read(input), itoa(1337)], [';']));
 | 
				
			||||||
		Loading…
	
		Reference in New Issue