move boolean output and character input to subroutine, change memlib comments
This commit is contained in:
		
							parent
							
								
									04489721f7
								
							
						
					
					
						commit
						eae3c68b51
					
				| 
						 | 
				
			
			@ -87,6 +87,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
			
		|||
		try {
 | 
			
		||||
			String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$
 | 
			
		||||
			prog = Assembler.instance().assemble(memlib);
 | 
			
		||||
 | 
			
		||||
			String stdlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("stdlib.iloc"))); //$NON-NLS-1$
 | 
			
		||||
			Program prog2 = Assembler.instance().assemble(stdlib);
 | 
			
		||||
			try {
 | 
			
		||||
				for (Instr instr : prog2.getInstr())
 | 
			
		||||
					prog.addInstr(instr);
 | 
			
		||||
			} catch (Throwable t) {
 | 
			
		||||
				t.printStackTrace(System.err);
 | 
			
		||||
			}
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new RuntimeException(e);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -823,88 +832,30 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
			
		|||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Reg visitRead(ReadContext ctx) {
 | 
			
		||||
		if (ctx.variable().size() > 1) {
 | 
			
		||||
		Reg res = null;
 | 
			
		||||
		for (VariableContext expr : ctx.variable()) {
 | 
			
		||||
			visit(expr);
 | 
			
		||||
 | 
			
		||||
				if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
 | 
			
		||||
					regPool.withReg((temp) -> {
 | 
			
		||||
			if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr)))
 | 
			
		||||
				res = regPool.withReg((temp) -> {
 | 
			
		||||
					emit("", OpCode.in, new Str(""), temp); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
					Reg addr = visit(expr);
 | 
			
		||||
					emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$
 | 
			
		||||
				});
 | 
			
		||||
				} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
 | 
			
		||||
					// Get input until at least 1 character
 | 
			
		||||
					Label getTarget = makeLabel("lcin_l"); //$NON-NLS-1$
 | 
			
		||||
					Label continueTarget = makeLabel("lcin_e"); //$NON-NLS-1$
 | 
			
		||||
 | 
			
		||||
					regPool.withReg((temp, count) -> {
 | 
			
		||||
						emit("", getTarget, OpCode.cin, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
						emit("str length", OpCode.pop, count); //$NON-NLS-1$
 | 
			
		||||
						emit("repeat if 0 length", OpCode.cbr, count, continueTarget, getTarget); //$NON-NLS-1$
 | 
			
		||||
 | 
			
		||||
						// Get character
 | 
			
		||||
						emit("pop whole string", continueTarget, OpCode.cpop, temp); //$NON-NLS-1$
 | 
			
		||||
			else if (SimpleType.CHAR.equals(an.types.get(expr)))
 | 
			
		||||
				res = regPool.withReg((temp) -> {
 | 
			
		||||
					emit("call stdcin", OpCode.loadI, new Num(prog.size() + 3), temp); //$NON-NLS-1$
 | 
			
		||||
					emit("call stdcin", OpCode.push, temp); //$NON-NLS-1$
 | 
			
		||||
					emit("call stdcin", OpCode.jumpI, new Label("stdcin")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
					emit("get character", OpCode.cpop, temp); //$NON-NLS-1$
 | 
			
		||||
					Reg addr = visit(expr);
 | 
			
		||||
					emit("save to var " + expr.getText(), OpCode.cstore, temp, addr); //$NON-NLS-1$
 | 
			
		||||
 | 
			
		||||
						// Pop all remaining characters
 | 
			
		||||
						Label loopTarget = makeLabel("lcpop_l"); //$NON-NLS-1$
 | 
			
		||||
						Label iterTarget = makeLabel("lcpop_c"); //$NON-NLS-1$
 | 
			
		||||
						Label stopTarget = makeLabel("lcpop_e"); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", loopTarget, OpCode.subI, count, new Num(1), temp); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", OpCode.cbr, count, iterTarget, stopTarget); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", iterTarget, OpCode.cpop, temp); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", OpCode.jumpI, loopTarget); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", stopTarget, OpCode.nop); //$NON-NLS-1$
 | 
			
		||||
				});
 | 
			
		||||
				} else {
 | 
			
		||||
			else
 | 
			
		||||
				emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
 | 
			
		||||
		}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		} else {
 | 
			
		||||
			VariableContext expr = ctx.variable(0);
 | 
			
		||||
 | 
			
		||||
			if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
 | 
			
		||||
				return regPool.withReg((result) -> {
 | 
			
		||||
					emit("", OpCode.in, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
					Reg addr = visit(expr);
 | 
			
		||||
					emit("save to var " + expr.getText(), OpCode.store, result, addr); //$NON-NLS-1$
 | 
			
		||||
				});
 | 
			
		||||
			} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
 | 
			
		||||
				return regPool.withReg((count, result) -> {
 | 
			
		||||
					// Get input until at least 1 character
 | 
			
		||||
					Label getTarget = makeLabel("lcin_l"); //$NON-NLS-1$
 | 
			
		||||
					Label continueTarget = makeLabel("lcin_e"); //$NON-NLS-1$
 | 
			
		||||
 | 
			
		||||
					emit("", getTarget, OpCode.cin, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
					emit("str length", OpCode.pop, count); //$NON-NLS-1$
 | 
			
		||||
					emit("repeat if 0 length", OpCode.cbr, count, continueTarget, getTarget); //$NON-NLS-1$
 | 
			
		||||
 | 
			
		||||
					// Get character
 | 
			
		||||
					emit("pop whole string", continueTarget, OpCode.cpop, result); //$NON-NLS-1$
 | 
			
		||||
					Reg addr = visit(expr);
 | 
			
		||||
					emit("save to var " + expr.getText(), OpCode.cstore, result, addr); //$NON-NLS-1$
 | 
			
		||||
 | 
			
		||||
					// Pop all remaining characters
 | 
			
		||||
					Label loopTarget = makeLabel("lcpop_l"); //$NON-NLS-1$
 | 
			
		||||
					Label iterTarget = makeLabel("lcpop_c"); //$NON-NLS-1$
 | 
			
		||||
					Label stopTarget = makeLabel("lcpop_e"); //$NON-NLS-1$
 | 
			
		||||
					regPool.withReg((temp) -> {
 | 
			
		||||
						emit("pop remaining", loopTarget, OpCode.subI, count, new Num(1), count); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", OpCode.cbr, count, iterTarget, stopTarget); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", iterTarget, OpCode.cpop, temp); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", OpCode.jumpI, loopTarget); //$NON-NLS-1$
 | 
			
		||||
						emit("pop remaining", stopTarget, OpCode.nop); //$NON-NLS-1$
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			} else {
 | 
			
		||||
				emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
 | 
			
		||||
				return null;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return res;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -1010,14 +961,20 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
			
		|||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Reg visitWrite(WriteContext ctx) {
 | 
			
		||||
		if (ctx.expr().size() > 1) {
 | 
			
		||||
		for (ExprContext expr : ctx.expr()) {
 | 
			
		||||
			Reg result = visit(expr);
 | 
			
		||||
 | 
			
		||||
			regPool.blockReg(result, () -> {
 | 
			
		||||
				Type type = an.types.get(expr);
 | 
			
		||||
 | 
			
		||||
					if (SimpleType.BOOL.equals(type) || SimpleType.INT.equals(type)) {
 | 
			
		||||
				if (SimpleType.BOOL.equals(type)) {
 | 
			
		||||
					regPool.withReg((temp) -> {
 | 
			
		||||
						emit("call stdbout", OpCode.loadI, new Num(prog.size() + 4), temp); // $NON-NLS-2$ //$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.jumpI, new Label("stdbout")); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
					});
 | 
			
		||||
				} else if (SimpleType.INT.equals(type)) {
 | 
			
		||||
					emit("", OpCode.out, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
				} else if (SimpleType.CHAR.equals(type)) {
 | 
			
		||||
					regPool.withReg((temp) -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1034,31 +991,11 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
 | 
			
		|||
					if (type instanceof ReferenceType)
 | 
			
		||||
						decrementReference(type, result);
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			if (ctx.expr().size() == 1)
 | 
			
		||||
				return result;
 | 
			
		||||
		}
 | 
			
		||||
			return null;
 | 
			
		||||
		} else {
 | 
			
		||||
			ExprContext expr = ctx.expr(0);
 | 
			
		||||
			Reg result = visit(expr);
 | 
			
		||||
 | 
			
		||||
			return regPool.blockReg(result, () -> {
 | 
			
		||||
				Type type = an.types.get(expr);
 | 
			
		||||
 | 
			
		||||
				if (SimpleType.BOOL.equals(type) || SimpleType.INT.equals(type)) {
 | 
			
		||||
					emit("", OpCode.out, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
 | 
			
		||||
					return result;
 | 
			
		||||
				} else if (SimpleType.CHAR.equals(type)) {
 | 
			
		||||
					regPool.withReg((temp) -> {
 | 
			
		||||
						emit("push character", OpCode.cpush, result); //$NON-NLS-1$
 | 
			
		||||
						emit("load 1", OpCode.loadI, new Num(1), 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$
 | 
			
		||||
					});
 | 
			
		||||
					return result;
 | 
			
		||||
				} else {
 | 
			
		||||
					emit("writing unknown type", OpCode.haltI, new Num(0x77726974)); //$NON-NLS-1$
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ memlib_: loadI    0 => m_0
 | 
			
		|||
// allocate memory
 | 
			
		||||
// searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at
 | 
			
		||||
// least #4+16
 | 
			
		||||
// memory: [return address, object size] -> [object address]
 | 
			
		||||
// stack: [return address, object size] -> [object address]
 | 
			
		||||
memalloc: loadI    0 => m_0
 | 
			
		||||
          pop      => m_s                        // load size
 | 
			
		||||
          loadI    @fst_ptr => m_p               // load previous address (base pointer)
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ ma_null:  pop      => m_1                        // load return address
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
// increase reference count of object
 | 
			
		||||
// memory: [return address, object address] -> []
 | 
			
		||||
// stack: [return address, object address] -> []
 | 
			
		||||
memaddref: loadI    0 => m_0
 | 
			
		||||
           pop      => m_n                       // load object address
 | 
			
		||||
           cmp_EQ   m_0,m_n => m_1
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ mr_nnul:   loadAI   m_n,@off_oref => m_1
 | 
			
		|||
 | 
			
		||||
// decrease reference count of object
 | 
			
		||||
// frees memory if count goes to zero
 | 
			
		||||
// memory: [return address, object address] -> []
 | 
			
		||||
// stack: [return address, object address] -> []
 | 
			
		||||
memfree: loadI    0 => m_0
 | 
			
		||||
         pop      => m_n                         // load object address
 | 
			
		||||
         cmp_EQ   m_0,m_n => m_1
 | 
			
		||||
| 
						 | 
				
			
			@ -111,8 +111,8 @@ mf_free: subI     m_n,@header => m_n
 | 
			
		|||
         loadI    @fst_ptr => m_p
 | 
			
		||||
         loadAI   m_p,@off_next => m_c
 | 
			
		||||
 | 
			
		||||
mf_loop: cmp_EQ   m_0,m_c => m_1                 // check if address pointer is null
 | 
			
		||||
         cbr      m_1 -> mf_halt,mf_cont
 | 
			
		||||
mf_loop: cmp_EQ   m_0,m_c => m_1                 // loop until the surrounding free blocks are found
 | 
			
		||||
         cbr      m_1 -> mf_halt,mf_cont         // check if address pointer is null
 | 
			
		||||
mf_halt: haltI    1882220141                     // halt program; object beyond last free slot (or memory corrupted)
 | 
			
		||||
mf_cont: cmp_EQ   m_c,m_n => m_1
 | 
			
		||||
         cbr      m_1 -> mf_hal2,mf_con2
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +152,7 @@ mf_nnxt: storeAI  m_c => m_n,@off_next           // link new free slot with next
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
// copy object to location
 | 
			
		||||
// memory: [return address, object address, destination] -> []
 | 
			
		||||
// stack: [return address, object address, destination] -> []
 | 
			
		||||
memcopy: loadI    0 => m_0
 | 
			
		||||
         haltI    1835626101                     // unimplemented
 | 
			
		||||
         pop      => m_1                         // load return address
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
// stdlib - generic subroutines for ILOC
 | 
			
		||||
//
 | 
			
		||||
// This library contains a few common subroutines for Boppi.
 | 
			
		||||
//
 | 
			
		||||
// @author Frank Wibbelink
 | 
			
		||||
 | 
			
		||||
// initialise
 | 
			
		||||
stdlib_: jumpI -> estdlib_
 | 
			
		||||
 | 
			
		||||
// write a boolean to output
 | 
			
		||||
// stack: [return address, bool] -> []
 | 
			
		||||
stdbout: pop => m_1                 // get boolean
 | 
			
		||||
         loadI 0 => m_2             // load zero-length string
 | 
			
		||||
         push m_2
 | 
			
		||||
         cbr m_1 -> sbout_t,sbout_f
 | 
			
		||||
sbout_t: cout "true"
 | 
			
		||||
         jumpI -> sbout_e
 | 
			
		||||
sbout_f: cout "false"
 | 
			
		||||
sbout_e: pop => m_1                 // load return address
 | 
			
		||||
         jump -> m_1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// read a character from input
 | 
			
		||||
// stack: [return address] -> [char]
 | 
			
		||||
stdcin:  cin "" // get line
 | 
			
		||||
         pop => m_1 // get length
 | 
			
		||||
         cbr m_1 -> scin_t,stdcin   // repeat until at least one character
 | 
			
		||||
scin_t:  cpop => m_2                // save character
 | 
			
		||||
scin_lc: subI m_1, 1 => m_1         // decrement char count
 | 
			
		||||
         cbr m_1 -> scin_ll,scin_le
 | 
			
		||||
scin_ll: cpop => m_0                // discard character
 | 
			
		||||
         jumpI -> scin_lc           // repeat
 | 
			
		||||
scin_le: loadI 0 => m_0             // reset zero register
 | 
			
		||||
         pop => m_1                 // get return address
 | 
			
		||||
         cpush m_2                  // push result character
 | 
			
		||||
         jump -> m_1
 | 
			
		||||
 | 
			
		||||
estdlib_: nop
 | 
			
		||||
// end of stdlib
 | 
			
		||||
		Loading…
	
		Reference in New Issue