move boolean output and character input to subroutine, change memlib comments

This commit is contained in:
User 2017-11-28 16:39:02 +01:00
parent 04489721f7
commit eae3c68b51
3 changed files with 90 additions and 114 deletions

View File

@ -87,6 +87,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
try { try {
String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$ String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$
prog = Assembler.instance().assemble(memlib); 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) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -823,88 +832,30 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
@Override @Override
public Reg visitRead(ReadContext ctx) { public Reg visitRead(ReadContext ctx) {
if (ctx.variable().size() > 1) { Reg res = null;
for (VariableContext expr : ctx.variable()) { for (VariableContext expr : ctx.variable()) {
visit(expr); visit(expr);
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) { if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr)))
regPool.withReg((temp) -> { res = regPool.withReg((temp) -> {
emit("", OpCode.in, new Str(""), temp); //$NON-NLS-1$ //$NON-NLS-2$ emit("", OpCode.in, new Str(""), temp); //$NON-NLS-1$ //$NON-NLS-2$
Reg addr = visit(expr); Reg addr = visit(expr);
emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$ emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$
}); });
} else if (SimpleType.CHAR.equals(an.types.get(expr))) { else if (SimpleType.CHAR.equals(an.types.get(expr)))
// Get input until at least 1 character res = regPool.withReg((temp) -> {
Label getTarget = makeLabel("lcin_l"); //$NON-NLS-1$ emit("call stdcin", OpCode.loadI, new Num(prog.size() + 3), temp); //$NON-NLS-1$
Label continueTarget = makeLabel("lcin_e"); //$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$
regPool.withReg((temp, count) -> { emit("get character", OpCode.cpop, temp); //$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, temp); //$NON-NLS-1$
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$
// 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$ emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
} }
}
return null; return res;
} 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;
}
}
} }
@Override @Override
@ -1010,14 +961,20 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
@Override @Override
public Reg visitWrite(WriteContext ctx) { public Reg visitWrite(WriteContext ctx) {
if (ctx.expr().size() > 1) {
for (ExprContext expr : ctx.expr()) { for (ExprContext expr : ctx.expr()) {
Reg result = visit(expr); Reg result = visit(expr);
regPool.blockReg(result, () -> { regPool.blockReg(result, () -> {
Type type = an.types.get(expr); 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$ emit("", OpCode.out, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
} else if (SimpleType.CHAR.equals(type)) { } else if (SimpleType.CHAR.equals(type)) {
regPool.withReg((temp) -> { regPool.withReg((temp) -> {
@ -1034,31 +991,11 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
if (type instanceof ReferenceType) if (type instanceof ReferenceType)
decrementReference(type, result); 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; return null;
} }
});
}
}
} }

View File

@ -36,7 +36,7 @@ memlib_: loadI 0 => m_0
// allocate memory // allocate memory
// searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at // searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at
// least #4+16 // least #4+16
// memory: [return address, object size] -> [object address] // stack: [return address, object size] -> [object address]
memalloc: loadI 0 => m_0 memalloc: loadI 0 => m_0
pop => m_s // load size pop => m_s // load size
loadI @fst_ptr => m_p // load previous address (base pointer) 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 // increase reference count of object
// memory: [return address, object address] -> [] // stack: [return address, object address] -> []
memaddref: loadI 0 => m_0 memaddref: loadI 0 => m_0
pop => m_n // load object address pop => m_n // load object address
cmp_EQ m_0,m_n => m_1 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 // decrease reference count of object
// frees memory if count goes to zero // frees memory if count goes to zero
// memory: [return address, object address] -> [] // stack: [return address, object address] -> []
memfree: loadI 0 => m_0 memfree: loadI 0 => m_0
pop => m_n // load object address pop => m_n // load object address
cmp_EQ m_0,m_n => m_1 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 loadI @fst_ptr => m_p
loadAI m_p,@off_next => m_c loadAI m_p,@off_next => m_c
mf_loop: cmp_EQ m_0,m_c => m_1 // check if address pointer is null 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 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_halt: haltI 1882220141 // halt program; object beyond last free slot (or memory corrupted)
mf_cont: cmp_EQ m_c,m_n => m_1 mf_cont: cmp_EQ m_c,m_n => m_1
cbr m_1 -> mf_hal2,mf_con2 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 // copy object to location
// memory: [return address, object address, destination] -> [] // stack: [return address, object address, destination] -> []
memcopy: loadI 0 => m_0 memcopy: loadI 0 => m_0
haltI 1835626101 // unimplemented haltI 1835626101 // unimplemented
pop => m_1 // load return address pop => m_1 // load return address

View File

@ -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